Page 2 of 2
Re: Local iterator functions slower than global?
Posted: Sat Nov 11, 2017 7:40 am
by ivan
Limey wrote: ↑Fri Nov 10, 2017 8:27 pm
I had no idea variable name mattered when localizing.
Like I said, there is no significant advantage to localizing pairs or ipairs (in fact it could be detrimental with LuaJIT).
On the other hand localizing functions like 'math.cos' is beneficial since you're not doing the 'math.' lookup every time.
like, 'math.cos' var name should be 'cos' or, 'love.graphics.draw' var name should be 'draw'?
No, it doesn't have to be.
Re: Local iterator functions slower than global?
Posted: Sat Nov 11, 2017 1:34 pm
by slime
ivan wrote: ↑Sat Nov 11, 2017 7:40 am(in fact it could be detrimental with LuaJIT).
I see people say this a lot but it's generally based on a misinterpretation of
http://luajit.org/ext_ffi_tutorial.html#cache , which is specifically talking about localizing FFI-based C functions and nothing else. Mike Pall
still recommends localizing Lua functions (including Lua's standard library APIs, most of which are something a bit different from FFI-based C APIs, traditional C Lua APIs,
and Lua-defined functions).
Re: Local iterator functions slower than global?
Posted: Sun Nov 12, 2017 6:57 am
by ivan
slime, the tests confirm that using local L_next, L_pairs, L_ipairs = next, pairs, ipairs is slower with LuaJIT.
local next, pairs, ipairs = next, pairs, ipairs makes no significant difference to compared to simply using globals.
Localizing functions in modules (string.format, math.cos, etc) can be significantly faster though.
Re: Local iterator functions slower than global?
Posted: Sun Nov 12, 2017 10:20 am
by bartbes
But as was explained above, that's because the iterators specifically have special codepaths that are apparently sensitive to the function name. We have also seen that if you name the locals the same, it does have a (very small) positive effect.
Anyway, it seems like the moral of the story, as ever, is that when you're optimising you should measure.
Re: Local iterator functions slower than global?
Posted: Sun Nov 12, 2017 10:26 am
by slime
ivan wrote: ↑Sun Nov 12, 2017 6:57 am
slime, the tests confirm that using local L_next, L_pairs, L_ipairs = next, pairs, ipairs is slower with LuaJIT.
I restructured your test file a bit and that's not what I see.
Code:
Code: Select all
local clock = function() return love.timer.getTime()*1000 end
--local clock = function() return os.clock()*1000 end
function test(func, n)
local t1 = clock()
func(n)
local t2 = clock()
return t2 - t1
end
local tests = {}
function tests.G_pairs(t)
for k,v in pairs(t) do end
end
function tests.G_ipairs(t)
for k,v in ipairs(t) do end
end
function tests.G_next(t)
for k,v in next,t do end
end
do
local pairs = pairs
function tests.L_pairs(t)
for k,v in pairs(t) do end
end
end
do
local ipairs = ipairs
function tests.L_ipairs(t)
for k,v in ipairs(t) do end
end
end
do
local next = next
function tests.L_next(t)
for k,v in next,t do end
end
end
function tests.numeric(t)
for i = 1, #t do local v = t[i] end
end
local tbl1, tbl2 = { }, { }
for i = 1, 1000000 do
tbl1["id:" .. i] = i
tbl2[i] = i
end
local orderedtests = {
"G_pairs",
"L_pairs",
"G_ipairs",
"L_ipairs",
"G_next",
"L_next",
}
local runindex = 0
function run()
runindex = runindex + 1
print("Run " .. runindex)
collectgarbage()
print(' table')
for k, v in ipairs(orderedtests) do
local dt = test(tests[v], tbl1)
local res = string.format(" %s %f", v, dt)
print(res)
end
print(' list')
for k, v in ipairs(orderedtests) do
local dt = test(tests[v], tbl2)
local res = string.format(" %s %f", v, dt)
print(res)
end
end
function love.keypressed( key )
if key == "r" then
run()
elseif key == "escape" then
love.event.quit()
end
end
Results for 5 runs:
Code: Select all
Run 1
table
G_pairs 7.001184
L_pairs 6.140291
G_ipairs 0.000703
L_ipairs 0.000241
G_next 6.049011
L_next 5.884710
list
G_pairs 4.139990
L_pairs 4.099162
G_ipairs 1.233163
L_ipairs 1.238057
G_next 4.137121
L_next 4.103194
Run 2
table
G_pairs 7.419816
L_pairs 6.398329
G_ipairs 0.000797
L_ipairs 0.000340
G_next 6.009190
L_next 6.012991
list
G_pairs 4.129244
L_pairs 4.120332
G_ipairs 1.181987
L_ipairs 1.294385
G_next 4.138757
L_next 4.187949
Run 3
table
G_pairs 5.667696
L_pairs 4.881093
G_ipairs 0.000643
L_ipairs 0.000227
G_next 4.833117
L_next 4.984283
list
G_pairs 3.356417
L_pairs 3.433502
G_ipairs 1.000181
L_ipairs 0.925301
G_next 3.380838
L_next 3.437651
Run 4
table
G_pairs 5.487222
L_pairs 5.373785
G_ipairs 0.000764
L_ipairs 0.000400
G_next 5.328619
L_next 5.360983
list
G_pairs 3.611831
L_pairs 3.593776
G_ipairs 1.105480
L_ipairs 1.037402
G_next 3.601530
L_next 3.668182
Run 5
table
G_pairs 7.402496
L_pairs 6.652951
G_ipairs 0.000694
L_ipairs 0.000368
G_next 6.616921
L_next 6.577384
list
G_pairs 4.345796
L_pairs 4.371819
G_ipairs 1.476764
L_ipairs 1.392475
G_next 4.106316
L_next 4.103164
Results if I swap the order of the global and local tests:
Code: Select all
Run 1
table
L_pairs 6.791587
G_pairs 6.089623
L_ipairs 0.000967
G_ipairs 0.000344
L_next 6.018195
G_next 5.899110
list
L_pairs 4.100567
G_pairs 4.139295
L_ipairs 1.240099
G_ipairs 1.226358
L_next 4.147724
G_next 4.120191
Run 2
table
L_pairs 8.088988
G_pairs 7.181398
L_ipairs 0.000881
G_ipairs 0.000450
L_next 6.617171
G_next 7.379357
list
L_pairs 4.767215
G_pairs 4.204302
L_ipairs 1.403988
G_ipairs 1.248829
L_next 4.137867
G_next 4.382359
Run 3
table
L_pairs 8.070507
G_pairs 7.158387
L_ipairs 0.001047
G_ipairs 0.000650
L_next 6.187538
G_next 6.027564
list
L_pairs 4.250479
G_pairs 4.168065
L_ipairs 1.328489
G_ipairs 1.338998
L_next 4.215130
G_next 4.139268
Run 4
table
L_pairs 7.410009
G_pairs 6.451298
L_ipairs 0.000711
G_ipairs 0.000480
L_next 6.016515
G_next 6.016951
list
L_pairs 4.099409
G_pairs 4.145517
L_ipairs 1.202127
G_ipairs 1.277227
L_next 4.125294
G_next 4.141291
Run 5
table
L_pairs 7.360992
G_pairs 6.380586
L_ipairs 0.000707
G_ipairs 0.000433
L_next 6.026424
G_next 5.992165
list
L_pairs 4.139334
G_pairs 4.102957
L_ipairs 1.200363
G_ipairs 1.268221
L_next 4.114833
G_next 4.122798
ivan wrote: ↑Sun Nov 12, 2017 6:57 amlocal next, pairs, ipairs = next, pairs, ipairs makes no significant difference to compared to simply using globals.
Indeed.