= Things you should know about Lua's performance =
This wiki is a result of some lua performance tests (the widget is included with ca sandbox).
[[BR]][[BR]][[BR]] == TEST 1: localize ==Code:{ { { #!lualocal min = math.min}}}Results:{ { { #!html<div style="margin-left:25px"><font color="red" style="font-weight:bold">normal way: 0.719 (158%)</font><br><font color="green" style="font-weight:bold">localized: 0.453 (100%)</font></div>}}}Conclusion:{ { { -> Yeah, we should localize all used funtions.}}}== TEST 2: localized class-methods (with only 3 accesses!) ==
Code1:{ { { #!lua for i=1,1000000 do local x = class.test() local y = class.test() local z = class.test() end}}}Code2:{ { { #!lua for i=1,1000000 do local test = class.test local x = test() local y = test() local z = test() end}}}Results:{ { { #!html<div style="margin-left:25px">normal way: 1.203 (102%)<br>localized: 1.172 (100%)</div>}}}Conclusion:{ { { -> No, it isn't faster to localize a class method IN the function call.}}}== TEST 3: unpack a table ==
Code1:{ { { #!lua for i=1,1000000 do local x = min( a[1],a[2],a[3],a[4] ) end}}}Code2:{ { { #!lua local unpack = unpack for i=1,1000000 do local x = min( unpack(a) ) end}}}Code3:{ { { #!lua local function unpack4(a) return a[1],a[2],a[3],a[4] end for i=1,1000000 do local x = min( unpack4(a) ) end}}}Results:{ { { #!html<div style="margin-left:25px"><font color="green" style="font-weight:bold">with [ ]: 0.485 (100%)</font><br><font color="red" style="font-weight:bold">unpack(): 1.093 (225%)</font><br>custom unpack4: 0.641 (131%)</div>}}}Conclusion:{ { { -> Don't use unpack() in time critical code!}}}== TEST 4: determine maximum and set it ('>' vs. max) ==
Code1:{ { { #!lua local max = math.max for i=1,1000000 do x = max(random(cnt),x) end}}}Code2:{ { { #!lua for i=1,1000000 do local r = random(cnt) if (r>x) then x = r end end}}}Results:{ { { #!html<div style="margin-left:25px"><font color="red" style="font-weight:bold">math.max: 0.437 (156%)</font><br><font color="green" style="font-weight:bold">'if > then': 0.282 (100%)</font></div>}}}Conclusion:{ { { -> Don't use math.[max|min]() in time critical code!}}}== TEST 5: nil checks ('if' vs. 'or') ==
Code1:{ { { #!lua for i=1,1000000 do local y,x if (random()>0.5) then y=1 end if (y==nil) then x=1 else x=y end end}}}Code2:{ { { #!lua for i=1,1000000 do local y if (random()>0.5) then y=1 end local x=y or 1 end}}}Results:{ { { #!html<div style="margin-left:25px"><font color="red" style="font-weight:bold">nil-check: 0.297 (106%)</font><br><font color="green" style="font-weight:bold">a=x or y: 0.281 (100%)</font></div>}}}Conclusion:{ { { -> WOW! the or-operator is faster than a nil-check. Use it! :D}}}== TEST 6: 'x^2^' vs. 'x*x' ==
Code1:{ { { #!lua for i=1,1000000 do local y = x^2 end}}}Code2:{ { { #!lua for i=1,1000000 do local y = x*x end}}}Results:{ { { #!html<div style="margin-left:25px"><font color="red" style="font-weight:bold">x^2: 1.422 (110%)</font><br><font color="green" style="font-weight:bold">x*x: 1.297 (100%)</font></div>}}}== TEST 7: modulus operators (math.mod vs. %) ==
Code1:{ { { #!lua local fmod = math.fmod for i=1,1000000 do if (fmod(i,30)<1) then local x = 1 end end}}}Code2:{ { { #!lua for i=1,1000000 do if ((i%30)<1) then local x = 1 end end}}}Results:{ { { #!html<div style="margin-left:25px"><font color="red" style="font-weight:bold">math.mod: 0.281 (355%)</font><br><font color="green" style="font-weight:bold">%: 0.079 (100%)</font></div>}}}Conclusion:{ { { -> Don't use math.fmod() for positive numbers (for negative ones % and fmod() have different results!)!}}}== TEST 8: functions as param for other functions ==
Code1:{ { { #!lua local func1 = function(a,b,func) return func(a+b) endfor i=1,1000000 do
local x = func1(1,2,function(a) return a*2 end) end}}}Code2:{ { { #!lua local func1 = function(a,b,func) return func(a+b) end local func2 = function(a) return a*2 endfor i=1,1000000 do
local x = func1(1,2,func2) end}}}Results:{ { { #!html<div style="margin-left:25px"><font color="red" style="font-weight:bold">defined in function param: 3.890 (1144%)</font><br><font color="green" style="font-weight:bold">defined as local: 0.344 (100%)</font></div>}}}Conclusion:{ { { -> REALLY, LOCALIZE YOUR FUNCTIONS ALWAYS BEFORE SENDING THEM INTO ANOTHER FUNCTION!!! i.e if you use gl.BeginEnd(), gl.CreateList(), ...!!!}}}== TEST 9: for-loops ==
Code1:{ { { #!lua for i=1,1000000 do for j,v in pairs(a) do x=v end end}}}Code2:{ { { #!lua for i=1,1000000 do for j,v in ipairs(a) do x=v end end}}}Code3:{ { { #!lua for i=1,1000000 do for i=1,100 do x=a[i] end end}}}Code4:{ { { #!lua for i=1,1000000 do for i=1,#a do x=a[i] end end}}}Code5:{ { { #!lua for i=1,1000000 do local length = #a for i=1,length do x=a[i] end end}}}Results:{ { { #!html<div style="margin-left:25px">pairs: 3.078 (217%)<br><font color="red" style="font-weight:bold">ipairs: 3.344 (236%)</font><br><font color="green" style="font-weight:bold">for i=1,x do: 1.422 (100%)</font><br>for i=1,#atable do 1.422 (100%)<br>for i=1,atable_length do: 1.562 (110%)</div>}}}Conclusion:{ { { -> Don't use pairs() or ipairs()! Try to save the table-size somewhere and use "for i=1,x do"!}}}== TEST 10: array access (with [ ]) vs. object access (with .method) ==
Code1:{ { { #!lua for i=1,1000000 do x = a["foo"] end}}}Code2:{ { { #!lua for i=1,1000000 do x = a.foo end}}}Results:{ { { #!html<div style="margin-left:25px">atable["foo"]: 1.125 (100%)<br>atable.foo: 1.141 (101%)</div>}}}== TEST 11: buffered table item access ==
Code1:{ { { #!lua for i=1,1000000 do for n=1,100 do a[n].x=a[n].x+1 end end}}}Code2:{ { { #!lua for i=1,1000000 do for n=1,100 do local y = a[n] y.x=y.x+1 end end}}}Results:{ { { #!html<div style="margin-left:25px"><font color="red" style="font-weight:bold">'a[n].x=a[n].x+1': 1.453 (127%)</font><br><font color="green" style="font-weight:bold">'local y=a[n]; y.x=y.x+1': 1.140 (100%)</font></div>}}}== TEST 12: adding table items (table.insert vs. [ ]) ==
Code1:{ { { #!lua local tinsert = table.insert for i=1,1000000 do tinsert(a,i) end}}}Code2:{ { { #!lua for i=1,1000000 do a[i]=i end}}}Code3:{ { { #!lua for i=1,1000000 do a[#a+1]=i end}}}Code4:{ { { #!lua local count = 1 for i=1,1000000 do d[count]=i count=count+1 end}}}Results:{ { { #!html<div style="margin-left:25px"><font color="red" style="font-weight:bold">table.insert: 1.250 (727%)</font><br><font color="green" style="font-weight:bold">a[i]: 0.172 (100%)</font><br>a[#a+1]=x: 0.453 (263%)<br>a[count++]=x: 0.203 (118%)</div>}}}Conclusion:{ { { -> Don't use table.insert!!! Try to save the table-size somewhere and use "a[count+1]=x"!}}}