Just out of curiosity, since I am not a lua expert.
Is this fragment
local x
for i = 1, 1000 do
x = ...something...
end
faster then this
for i = 1, 1000 do
local x = ...something...
end
My apologize for the (most probably) silly question…
1 Like
It is just as easy to test by getting the time before and after the loops.
I think yes, there’s a lot of create & release variables in the second one (just my guess)
On my system the following
local y
local x
for i = 1, 10000000 do
x = i*i / 1000.0
y = y + x
end
is 0.5 millisecond faster then the version with local inside the loop. I measured the time with socket.gettime. Note that 0.1 millisecond is the precision of socket.gettime.
Conclusion: the time difference is 0.5 * 10^{-7} per loop cycle. I would say it is negligible for any reasonable use of lua as a scripting language.
3 Likes
In this case, the local variable is being created and destroyed with each pass through the loop, correct? It seems to me that this is not good.
The test say the difference is sooooo small 
It doesn’t matter. The time difference is insignificant.
I ran the following functions a million times, in alternating passes
local function empty() end
local function upvalue()
local x
for i = 1, 1000 do
x = i
end
end
local function localvalue()
for i = 1, 1000 do
local x = i
end
end
The times (in seconds) for each, summed up:
Total Iterations: 1000000
tests for ‘empty’ run in: 0.0099935930000018
tests for ‘localvalue’ run in: 0.280853607
tests for ‘upvalue’ run in: 0.281357203
The relative difference is only a fraction of a percent, in a million calls, and also far less than simply calling an empty function for the same number of times.
There is no difference.
3 Likes
In my experience, with LuaJIT, the only general “trick” that makes a difference in performance is “localizing” functions and other values to avoid repeated table accesses, for things that you are using repeatedly.
For example if your loop used a math function, set it to a local variable first, or if you’re accessing the same property or sub-property of a table in a loop, put it in a local variable first instead of accessing it repeatedly
local max = math.max
local function doSomething()
for i=1,1000 do
local v = max(...)
end
end
local function doSomethingWithObj(obj)
-- Localize here instead of accessing repeatedly inside the loop.
local prop = obj.thing.property
for i=1,1000 do
-- Do something with `prop`...
end
end
There are also some differences in cost between various built-in functions that may not be obvious of course, though unless you’re using them thousands of times it won’t matter. Otherwise, LuaJIT does all the optimization for you and makes abstractions free.
Regular Lua is much slower than LuaJIT as baseline, and also does not get the “no-cost abstraction” that LuaJIT gives you, but you would have to test specific code against alternatives to know what’s costly and what’s not.
5 Likes
some quick tips for lua optimization (based on my experience with non-JIT:
- use locals
- avoid excessive definitions
- avoid string manipulation
- don’t use ipairs
- avoid redundant function calls
as for your specific question, it’s best answered by looking at the compiled bytecode (compiled with lua 5.2). the first approach nets:
LOADNIL
LOADK
LOADK
LOADK
FORPREP
...
FORLOOP
while the second appoach nets
LOADK
LOADK
LOADK
FORPREP
...
FORLOOP
you can see there’s very little difference. performance wise they’d be nearly identical, but it really depends on your variable scope needs. If you need the variable x outside of the loop, then you can’t set it local inside.
1 Like