• Subject: Poor man's benchmarking issue - help needed
• From: Lorenzo Donati <lorenzodonatibz@...>
• Date: Wed, 31 Aug 2011 09:03:46 +0200

```Hi all!

```
I stumbled a funny result when doing very simple benchmarking on some of my code.
```
```
According to the following benchmarks, built-in math.floor and math.ceil are slower than their counterpart rewritten using the core % operator!
```
```
Since I found this unlikely, probably my home-brewed benchmarking function is borked, so I'd like some feedback about it.
```
This is the funny benchmark:

----------------------------------------------------
local StatTime = require 'ld.debug'.StatTime
local function flo( x ) return math.floor( x ) end
local function flo2( x ) return x - x%1 end
local function ce( x ) return math.ceil( x ) end
local function ce2( x ) return x - x%1 + 1 end

print(StatTime(1e8,{ flo, flo2 }, 5.5))  --> 2.4859e-007    1    0.579
print(StatTime(1e8,{ ce, ce2 }, 5.5))    --> 2.6688e-007    1    0.563
----------------------------------------------------

The printed values are:
--> average time of 1st func, 1, relative time of 2nd func

```
Here below the implementation of StatTime with the relative doc comments (using LDoc - thank you Steve :-)
```

---------------------------------------------------------
-- Measure the average execution time of a function calling
-- it repeatedly, or compare the relative execution time of a
-- set of functions.
--
-- If `func` is a function, it simply returns the average
-- execution time of the call `func(...)`, where `...` are
-- all the remaining arguments provided to the `StatTime`
-- function.
--
-- If `func` is an array of functions, then `StatTime` will
-- be called individually for each function and the results
-- will be divided by the average execution time of the first
-- element of the array. In this case `StatTime` will return
-- in order:
--
-- + the average execution time of `func[1]` in seconds;
-- + the number `1`;
-- + the average execution time of `func[2]` relative to `func[1]`;
-- + ...
-- + the average execution time of `func[#func]` relative to `func[1]`.
--
-- Relative times will be rounded to 3 decimal digits to
-- improve readability, since more precision is meaningless
-- without an higher accuracy timer (internally `StatTime`
-- uses `os.clock`).
--
-- @function StatTime
-- @param n (**number**) how many times the functions are to
-- be executed to compute the averages.
-- @param func (**function** | **table**) the function or the
-- array of functions to be executed.
-- @param ... the arguments (if any) to use in the function
-- calls.
-- @return the average execution time (see above for the details).
local M_StatTime
do
local function StatTime( n, func, ...  )
local t1, t2
collectgarbage 'collect'
collectgarbage 'collect'
collectgarbage 'stop'
t1 = os_clock()
for i = 1, n do
func( ... )
end
t2 = os_clock()
collectgarbage 'restart'
collectgarbage 'collect'
collectgarbage 'collect'
return ( t2 - t1 ) / n
end

--[[ local ]]
function M_StatTime( n, func, ... )
if type( func ) == 'function' then
return StatTime( n, func, ... )
end
assert( type( func ) == 'table', "#arg2: invalid value type" )
local times = {}
local ref_t = StatTime( n, func[ 1 ], ... )
times[ 1 ], times[ 2 ] = ref_t, 1
local t
for i = 2, #func do
t = StatTime( n, func[ i ], ... ) / ref_t
times[ i +1 ] = t - t % 0.001
end
return unpack( times )
end
end
M.StatTime = M_StatTime
----------------------------------------------------

Any feedback is welcome.
TIA

-- Lorenzo

```