Lua's performance

= 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:

{{{

#!lua

local min = math.min

}}}

Results:

{{{

#!html

<div >

<font color="red" >normal way: 0.719 (158%)</font><br>

<font color="green" >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 >

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 >

<font color="green" >with [ ]: 0.485 (100%)</font><br>

<font color="red" >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 >

<font color="red" >math.max: 0.437 (156%)</font><br>

<font color="green" >'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 >

<font color="red" >nil-check: 0.297 (106%)</font><br>

<font color="green" >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 >

<font color="red" >x^2: 1.422 (110%)</font><br>

<font color="green" >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 >

<font color="red" >math.mod: 0.281 (355%)</font><br>

<font color="green" >%: 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)

end

for 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

end

for i=1,1000000 do

local x = func1(1,2,func2)

end

}}}

Results:

{{{

#!html

<div >

<font color="red" >defined in function param: 3.890 (1144%)</font><br>

<font color="green" >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 >

pairs: 3.078 (217%)<br>

<font color="red" >ipairs: 3.344 (236%)</font><br>

<font color="green" >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 >

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 >

<font color="red" >'a[n].x=a[n].x+1': 1.453 (127%)</font><br>

<font color="green" >'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 >

<font color="red" >table.insert: 1.250 (727%)</font><br>

<font color="green" >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"!

}}}