Created
July 6, 2014 19:57
-
-
Save csfrancis/9068d7168f6614bbdb41 to your computer and use it in GitHub Desktop.
Revisions
-
csfrancis created this gist
Jul 6, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,71 @@ -- A timer that uses the rdtsc instruction to read the CPU timestamp counter. -- -- Requires DynAsm with Lua mode: https://github.com/luapower/dynasm -- -- Use it like this: -- -- local tsc_timer = require('tsc_timer') -- local t = tsc_timer.start() -- ... do some things ... -- t:stop() -- print(t:value()) -- -- value() returns the estimated number of milliseconds and the number of ticks elapsed -- local dynasm = require('dynasm') local ffi = require('ffi') local rdtsc = dynasm.loadstring [[ local ffi = require('ffi') local dasm = require('dasm') |.arch x64 |.actionlist actions local Dst = dasm.new(actions) | rdtsc | shl rdx, 32 | or rax, rdx | ret local code = Dst:build() return function() local _ = code return ffi.cast('uint64_t __cdecl (*)()', code)() end ]]() ffi.cdef [[ int usleep(uint32_t usec); ]] local _M = {} local mt = { __index = _M } function _M.initialize() if _M.ticks_per_sec ~= nil then return end local start_time = rdtsc() ffi.C.usleep(200000) local end_time = rdtsc() - start_time _M.ticks_per_sec = end_time * 5 end function _M.start() if _M.ticks_per_second == nil then _M.initialize() end return setmetatable({ start_time = rdtsc() }, mt) end function _M.stop(self) local end_time = rdtsc() if self.start_time == nil then error("timer has not been started") end if self.stop_time ~= nil then error("timer has already been stopped") end _M.end_time = end_time return _M.value(self) end function _M.value(self) return tonumber(self.end_time - self.start_time) / tonumber(self.ticks_per_sec) * 1000, tonumber(self.end_time - self.start_time) end return _M