I am aware that using string.lowerworks on numbers (eg. string.lower(2)) whereas calling :lower() on numbers (eg. (2):lower()) will result in an error.
However, using :lower() keeps the code shorter when not working with numbers (which is almost always the case here).
So, in terms of performance(which way is more efficient, and is this difference significant?) and conventions (is there a general preference by scripters?), would string.lower(str) or str:lower() be the better default option?
This question extends to several other string library functions that can also be called as methods of a string type, such as upper, sub, format, split, gsub, byte, et cetera. For example, string.format("Hello %s world!", "cruel") versus ("Hello %s world!"):format("cruel").
Theoretically, the static call string.lower should be faster than an object method call like someString:lower, although the difference would be incredibly minimal.
Saving the string funcs as a var then using them is the fastest:
lower = string.lower
lower("myString")
2nd fastest is plain using the string library string.lower("myString")
Last Place is method calling the library: s = "myString" ; s:lower()
Not in the slightest. My test setup called the functions 30 million times and the difference between first and last place is half a sec.
I prefer straight using the string library, then using method calls. I do not advice you save the function call unless you are using the function like 500000 times a sec, this goes for any library function.
Test Setup:
timer = require(game.ReplicatedStorage.Timer).new()
wait(5)
local lower, rep = string.lower, string.rep
local loops, strlen = 3e7, 1
local char = "F"
local var
timer:start()
for i=1,loops do
var = string.lower(string.rep(char,strlen))
end
timer:stop()
wait(1)
timer:start()
for i=1,loops do
var = char:rep(strlen):lower()
end
timer:stop()
wait(1)
timer:start()
for i=1,loops do
var = lower(rep(char,strlen))
end
timer:stop()
wait(1)
timer:results()
Being 0,2 s faster on 30 mln iterations is a micro-optimsation. It cannot be a real issue performance-wise.
Luau already optimized standard library functions like string.lower when the script is loaded so the difference is even more minimal.
Itâs always possible to âlocalizeâ the global accesses by using local max = math.max , but this is cumbersome - in practice itâs easy to forget to apply this optimization. To avoid relying on programmers remembering to do this, Luau implements a special optimization called âimportsâ, where most global chains such as math.max are resolved when the script is loaded instead of when the script is executed.
This optimization relies on being able to predict the shape of the environment table for a given function; this is possible due to global sandboxing, however this optimization is invalid in some cases:
str:lower() â fast
string.lower â faster
local lower = string.lower; lower(str) â fastest
I believe this is the order of operations.
However the performance difference is likely negligible and you wonât need to worry about it. (youâd need to be lowering millions of characters per step to notice a difference)
Does not matter. Wonât ever matter. If youâre doing millions of operations on strings and feel the need to use a certain way of calling a function then youâre bottlenecking yourself by using strings in the first place.
I should not that optimizations to luau are being made such that people are less inclined to localize library functions because they are equivalent in speed for many many operations.
This occurs because stringâs have an __index metamethod set in their metatable. Numbers do not have this.
Use whatever feels most idiomatic to you. Donât waste time by believing you need to be obsessed with micro-optimization. You wasting time if you are. If youâre stuck micro-optimizing then I would suggest that you have bigger issues with your code.
In this case, you had to put a string in parenthesis to :lower it. However the string.lower looks much nicer. You can basically use both. Whatever works for you. If you need a fast conversion (faster to code I mean.) then use :lower. Example: local lowerName = game.Players.LocalPlayer.Name:lower()
Other example: string.lower("MaKE THIs LoWERCasE")
Basically, if itâs a string by itself (e.g. "Testing") then use string.lower("Testing") but if itâs a string from an object (e.g. workspace.Part.Name) then probably use :lower for efficiency.
It doesnât matter which one you use. They both do the same thing, but str:lower() is faster to write, so thatâs the one I prefer to use.
In term of perfermance, you donât even need to be slightly concerned about them because the difference (if there even is one) will be so extremely small that it wonât effect anything.