Hi Res Timer |
|
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
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")
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
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
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 msThis looks pretty good, much better than the windows results.
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