Hi Res Timer

lua-users home
wiki

A high resolution timer on most windows platforms (only). (Checked with LuaForWindows_v5.1.4-35)

This is used by BenchmarkModule, my benchmarking toolkit.

HiResTimer.lua

---------------------------
-- this module provide a function
-- HiResTimer.clock() which returns a high resolution timer
---------------------------
module("HiResTimer",package.seeall)

--
-- take the alien module
--
local alien=require"alien"

--
-- get the kernel dll
--
local kernel32=alien.load("kernel32.dll")

--
-- get dll functions
--
local QueryPerformanceCounter=kernel32.QueryPerformanceCounter
QueryPerformanceCounter:types{ret="int",abi="stdcall","pointer"}
local QueryPerformanceFrequency=kernel32.QueryPerformanceFrequency
QueryPerformanceFrequency:types{ret="int",abi="stdcall","pointer"}

--------------------------------------------
--- utility : convert a long to an unsigned long value
-- (because alien does not support longlong nor ulong)
--------------------------------------------
local function lu(long)
	return long<0 and long+0x80000000+0x80000000 or long
end

--------------------------------------------
--- Query the performance frequency.
-- @return (number)
--------------------------------------------
local function qpf()
	local frequency=alien.array('long',2)
	QueryPerformanceFrequency(frequency.buffer)
	return  math.ldexp(lu(frequency[1]),0)
		    +math.ldexp(lu(frequency[2]),32)
end

--------------------------------------------
--- Query the performance counter.
-- @return (number)
--------------------------------------------
local function qpc()
	local counter=alien.array('long',2)
	QueryPerformanceCounter(counter.buffer)
	return	 math.ldexp(lu(counter[1]),0)
			+math.ldexp(lu(counter[2]),32)
end

--------------------------------------------
-- get the startup values
--------------------------------------------
local f0=qpf()
local c0=qpc()

--------------------------------------------
--- Return a hires clock
-- @return (number) elapsed seconds since load of the module
--------------------------------------------
function clock()
	local c1=qpc()
	return (c1-c0)/f0
end

return HiResTimer

Example, how to use

local hrt=require"HiResTimer"

local t0=hrt.clock()

for i=1,1000*1000 do
	local j=i*i
end

local t1=hrt.clock()

print("Took",t1-t0,"seconds")

Linux??

If anyone has a similar module for Linux, I'd be very interested. Any suggestions or corrections are welcome.

HiResTimer v.s. socket.gettime()

I've been using LuaSocket?'s gettime function as a generic high-resolution timer. It seems to work reasonably well on Windows, Linux, and BSD. Also, LuaSocket? is usually already present. -ScottVokes?

For me socket.gettime() is not hires enough. Check this one

local hrt=require"HiResTimer"
local socket=require"socket"
local function printf(...)
    io.write(string.format(...))
end
for loops=0,100000,1000 do
    printf("%6d loops ",loops)
    local t0=hrt.clock()
    for i=1,loops do local j=math.sin(123) end
    local t1=hrt.clock()
    printf("hrt=%9.3f ms",(t1-t0)*1000)
    local t0=socket.gettime()
    for i=1,loops do local j=math.sin(123) end
    local t1=socket.gettime()
    printf(" socket=%9.3f ms\n",(t1-t0)*1000)
    --if t1>t0 then  break end
end
Results (trunkated)
     0 loops hrt=    0.035 ms socket=    0.000 ms
  1000 loops hrt=    0.327 ms socket=    0.000 ms
  2000 loops hrt=    0.461 ms socket=    0.000 ms
  3000 loops hrt=    0.685 ms socket=    0.000 ms
  4000 loops hrt=    0.905 ms socket=    0.000 ms
  5000 loops hrt=    1.123 ms socket=    0.000 ms
  6000 loops hrt=    1.391 ms socket=    0.000 ms
  7000 loops hrt=    1.565 ms socket=    0.000 ms
  8000 loops hrt=    1.801 ms socket=   15.625 ms
  9000 loops hrt=    2.032 ms socket=    0.000 ms
 10000 loops hrt=    2.244 ms socket=    0.000 ms
:::
 90000 loops hrt=   22.061 ms socket=   15.625 ms
 91000 loops hrt=   20.248 ms socket=   31.250 ms
 92000 loops hrt=   22.713 ms socket=   15.625 ms
 93000 loops hrt=   22.575 ms socket=   15.625 ms
 94000 loops hrt=   21.200 ms socket=   15.625 ms
 95000 loops hrt=   22.974 ms socket=   15.625 ms
 96000 loops hrt=   21.370 ms socket=   31.250 ms
 97000 loops hrt=   23.359 ms socket=   31.250 ms
 98000 loops hrt=   21.953 ms socket=   15.625 ms
 99000 loops hrt=   22.304 ms socket=   15.625 ms
100000 loops hrt=   22.887 ms socket=   15.625 ms

(at least on windows) socket.gettime has a resolution of 64 ticks/second, the performancecounter used in hires is above 1000000 ticks/second (exact value may vary with the machine)

for the sake of completeness I've checked socket.gettime on a linux machine

local socket=require"socket"
local function printf(...)
	io.write(string.format(...))
end
for loops=0,100000,1000 do
	printf("%6d loops ",loops)
	local t0=socket.gettime()
	for i=1,loops do local j=math.sin(123) end
	local t1=socket.gettime()
	printf(" socket=%9.3f ms\n",(t1-t0)*1000)
end
Result
     0 loops  socket=    0.002 ms
  1000 loops  socket=    0.509 ms
  2000 loops  socket=    1.017 ms
  3000 loops  socket=    1.485 ms
  4000 loops  socket=    1.172 ms
  5000 loops  socket=    1.477 ms
  6000 loops  socket=    1.776 ms
  7000 loops  socket=    2.078 ms
  8000 loops  socket=    2.381 ms
  9000 loops  socket=    2.850 ms
 10000 loops  socket=    3.000 ms
::::
 90000 loops  socket=   25.086 ms
 91000 loops  socket=   25.474 ms
 92000 loops  socket=   25.696 ms
 93000 loops  socket=   25.991 ms
 94000 loops  socket=   26.368 ms
 95000 loops  socket=   26.634 ms
 96000 loops  socket=   26.922 ms
 97000 loops  socket=   27.096 ms
 98000 loops  socket=   27.463 ms
 99000 loops  socket=   27.776 ms
100000 loops  socket=   27.973 ms
This looks pretty good, much better than the windows results.

- JoergenVonBargen

The above socket.gettime() code works well on Mac OS X (tested on 10.6.5) as well

Result

     0 loops  socket=    0.001 ms
  1000 loops  socket=    0.156 ms
  2000 loops  socket=    0.264 ms
  3000 loops  socket=    0.399 ms
  4000 loops  socket=    0.529 ms
  5000 loops  socket=    0.667 ms
...
 96000 loops  socket=   12.948 ms
 97000 loops  socket=   12.678 ms
 98000 loops  socket=   12.718 ms
 99000 loops  socket=   12.963 ms
100000 loops  socket=   12.949 ms

-- DougCurrie

See Also


RecentChanges · preferences
edit · history
Last edited January 4, 2011 5:21 am GMT (diff)