Extremely Non-Rigorous Benchmark

----------------------------------------------------------------
--speedups
----------------------------------------------------------------

local REPETITIONS = 10000000
----------------------------------------------------------------
--local functions
----------------------------------------------------------------


----------------------------------------------------------------
--callins
----------------------------------------------------------------

function widget:Initialize()
	local random = math.random
	local sqrt = math.sqrt
	local sin = math.sin
	local exp = math.exp
	local lastTime = os.clock()
	
	for i=1,REPETITIONS do

	end
	Spring.Echo("Empty loop: " .. (os.clock() - lastTime) .. "s");
	lastTime = os.clock()
	
	for i=1,REPETITIONS do
		local x = random()
		local y = random()
		local z = 0
	end
	Spring.Echo("Assignment-only loop: " .. (os.clock() - lastTime) .. "s");
	lastTime = os.clock()
	
	for i=1,REPETITIONS do
		local x = random()
		local y = random()
		local z = x + y
	end
	Spring.Echo("Plus loop: " .. (os.clock() - lastTime) .. "s");
	lastTime = os.clock()
	
	for i=1,REPETITIONS do
		local x = random()
		local y = random()
		local z = x * y
	end
	Spring.Echo("Mult loop: " .. (os.clock() - lastTime) .. "s");
	lastTime = os.clock()
	
	for i=1,REPETITIONS do
		local x = random()
		local y = random()
		local z = x / y
	end
	Spring.Echo("Divide loop: " .. (os.clock() - lastTime) .. "s");
	lastTime = os.clock()
	
	for i=1,REPETITIONS do
		local x = random()
		local y = random()
		local z = sqrt(x)
	end
	Spring.Echo("Sqrt loop: " .. (os.clock() - lastTime) .. "s");
	lastTime = os.clock()
	
	for i=1,REPETITIONS do
		local x = random()
		local y = random()
		local z = sin(x)
	end
	Spring.Echo("Sin loop: " .. (os.clock() - lastTime) .. "s");
	lastTime = os.clock()
	
	for i=1,REPETITIONS do
		local x = random()
		local y = random()
		local z = exp(x)
	end
	Spring.Echo("Exp loop: " .. (os.clock() - lastTime) .. "s");
	lastTime = os.clock()
end

on a Core 2 Duo E6750.

Results:
Empty loop: 0.062995910644531s
Assignment-only loop: 1.5780029296875s
Plus loop: 1.5309982299805s
Mult loop: 1.5s
Divide loop: 1.531005859375s
Sqrt loop: 3.625s
Sin loop: 2.6100006103516s
Exp loop: 2.6559906005859s

Multiplication is faster than assigning to a constant and addition O.o (granted, it is floats, not ints, but still…)

Assignment-only loop: 1.5780029296875s Plus loop: 1.5309982299805s Mult loop: 1.5s Divide loop: 1.531005859375s

IMO all of those are approx. the same, with some random inaccuracy in time measurement. So on the next run they may end up in different order (did you try at least 3 runs by the way? Any less give statistically unreliable results).
sin and exp being the same are more interesting, though not by much. sqrt being heavier than them is an important find, yet still sqrt is only 2.3 times as heavy as basic multiplication.

Good idea, I ran it four times in a loop:

[   3450] Empty loop: 0.06298828125s
[   3450] Assignment-only loop: 1.5780029296875s
[   3450] Plus loop: 1.5s
[   3450] Mult loop: 1.5160064697266s
[   3450] Divide loop: 1.5s
[   3450] Sqrt loop: 3.5780029296875s
[   3450] Sin loop: 2.5469970703125s
[   3450] Exp loop: 2.5309906005859s
[   3450] Trivial function loop: 2.31201171875s
[   3450] Empty loop: 0.078994750976563s
[   3450] Assignment-only loop: 1.5780029296875s
[   3450] Plus loop: 1.5s
[   3450] Mult loop: 1.5s
[   3450] Divide loop: 1.5s
[   3450] Sqrt loop: 3.5930023193359s
[   3450] Sin loop: 2.5469970703125s
[   3450] Exp loop: 2.5319976806641s
[   3450] Trivial function loop: 2.3280029296875s
[   3450] Empty loop: 0.0780029296875s
[   3450] Assignment-only loop: 1.5779876708984s
[   3450] Plus loop: 1.5s
[   3450] Mult loop: 1.5160064697266s
[   3450] Divide loop: 1.4839935302734s
[   3450] Sqrt loop: 3.5940093994141s
[   3450] Sin loop: 2.5469970703125s
[   3450] Exp loop: 2.531005859375s
[   3450] Trivial function loop: 2.3119964599609s
[   3450] Empty loop: 0.0780029296875s
[   3450] Assignment-only loop: 1.5789947509766s
[   3450] Plus loop: 1.5s
[   3450] Mult loop: 1.531005859375s
[   3450] Divide loop: 1.5149841308594s
[   3450] Sqrt loop: 3.6100158691406s
[   3450] Sin loop: 2.593994140625s
[   3450] Exp loop: 2.5150146484375s
[   3450] Trivial function loop: 2.3279724121094s

Trivial function is

local function Trivial()
	return 0
end

Plus, multiply, and divide seem to go back and forth, assigning to a constant seems more expensive still O.o. Sin and exp go back and forth too. Sqrt remains more costly.

Very odd results then. Assignment happens during all test stages, why would it be heavier on the first one… Let’s see what is unique in the first group:

local z = 0

This should be the cause then. Probably it tries to determine what type suits z best, while all the rest have their type determined by functions (random() can only return float, so x and y are always floats, no guesswork necessery). So, it we have a function that always returns 0 (but not a constant 0, rather something like 1-1), it can in theory be faster than a constant 0. Probably the same thing makes a return 0 function slower than maths.

Another probability is that some kind of optimizer kicks in and eliminates function calls the results of which are unused during current loop, but I haven’t heard of lua having something like that.

Of course, April the 1st cannot be fully ruled out of the test as well… :wink:

Lurker came (independently, I think) to similar conclusion about the assignment only test yesterday; he said he found that using local variables (or upvalues) was faster then using constants. Apparently assigning a constant to a variable is slightly slower even then performing a binary operation on 2 other variables and assigning the result to a variable.

The type doesn’t matter at all, if anything it would know about type of ‘0’ beforehand, and it wouldn’t know about type returned by ‘random()’ beforehand. (Lua doesn’t do any static type analysis of that kind.)