Hello guys! Did you know, that Roblox libraries, like string, table and others are metatables?
I think nope. Now you know.
And, do you know that if function uses : symbol, it passes first argument as itself? If you know metatables then you know this too.
But why I started with this 2 statements? They lead me to conclusion that we can type not long library name, and instead already pass our datatype with : symbol! But it’s important to note that this work NOT always, and it will make your code slower by 10-20%
In some cases you can do this:
local RandomText = "Hello, I'm 34124"
print(RandomText:match("%d+"))
Instead of
local RandomText = "Hello, I'm 34124"
print(string.match(RandomText, "%d+"))
If you don’t want to make variable, put brackets around datatype:
print(("Hello, I'm 34124"):match("%d+"))
That’s all!
Initially I thought that this will be good method to not write string and other datatypes constantly, but it has much worse outcomes, thanks to @BackspaceRGB for pointing that out!
If I remember correctly, this is considerably slower than using string., so be cautious.
EDIT: Quick test (not sure if this is actually how you do a benchmark lol)
Code:
local start = os.clock()
for i = 1, 1000000 do
local str = ("hello"):match("ello")
end
print(`string:match ended in {os.clock() - start}`)
local start = os.clock()
for i = 1, 1000000 do
local str = string.match("hello", "ello")
end
print(`string.match ended in {os.clock() - start}`)
Hm, never thought about that. Way I have suggested above is really slover by 10-20%.
I think I’ll rewrite this post so people WON’T make like that now…
I was using the str:match(...) pattern instead of string.match(str, ...) for over 10 years. Just this year, I switched back to using string.match(str, ...) (et. al.) due to the performance overhead. In reality, it’s more-so that Luau optimizes for global library functions and caches them, e.g. multiple accesses of string.match don’t have to do a hash lookup in the string library every time; just once.
local count = 1000000
for i = 1, count do
local str = "Hello world!"
string.match(str, "%s+")
end
local b = os.clock()
for i = 1, count do
local str = "Hello world!"
str:match("%s+")
end
local c = os.clock()
game.LogService:ClearOutput()
warn("string.match:", (b-a)*1000, "ms")
warn("str:match:", (c-b)*1000, "ms")
warn(`str:match is {math.floor((1-(b-a)/(c-b)) * 100)}% slower`)
It’s pretty random, so I would say it’s negligible.
I’ve researched on this in the past and I can definitely say that using the string methods on the actual string like "":upper() is ~(1 - 10)% slower than actually using string.upper("").
The percentage mainly depends on how frequently you’re messing around with strings. For a game that works a lot with strings, I’d recommend using string.method() instead of "":method
Due to global sandboxing and the ability to dynamically deoptimize code running in impure environments, in pure environments we go beyond optimizing the interpreter and optimize many built-in functions through a “fastcall” mechanism.
For this mechanism to work, function call must be “obvious” to the compiler - it needs to call a builtin function directly, e.g. math.max(x, 1), although it also works if the function is “localized” (local max = math.max); this mechanism doesn’t work for indirect function calls unless they were inlined during compilation, and doesn’t work for method calls (so calling string.byte is more efficient than s:byte).