Reputation: 5667
Is there a common way to get the current time in or with milliseconds?
There is os.time()
, but it only provides full seconds.
Upvotes: 91
Views: 195723
Reputation: 13738
If your environment is Windows and you have access to system commands, you can get time of centiseconds precision with io.popen(command)
:
local handle = io.popen("echo %time%")
local result = handle:read("*a")
handle:close()
The result will hold string of hh:mm:ss.cc
format: (with trailing line break)
"19:56:53.90\n"
Note, it's in local timezone, so you probably want to extract only the .cc
part and combine it with epoch seconds from os.time()
.
Upvotes: 1
Reputation: 10755
If you're on a system with a GNU-compatible implementation of date
that you can execute, here's a one-liner to get the Epoch time in milliseconds:
local function gethammertime()
return tonumber(assert(assert(io.popen'date +%s%3N'):read'a'))
end
Note that the assert
calls are necessary to ensure that any failures to read or open date
will propagate the errors, respectively. Also note that this relies on garbage collection (or finalizers, in Lua 5.4) to close the process handle: if using a pre-5.4 version of Lua and resource exhaustion is a concern, you may wish to extend this to three lines like Klesun's Windows-based answer and close the handle explicitly.
Upvotes: 3
Reputation: 8168
If you're using OpenResty then it provides for in-built millisecond time accuracy through the use of its ngx.now() function. Although if you want fine grained millisecond accuracy then you may need to call ngx.update_time() first. Or if you want to go one step further...
If you are using luajit enabled environment, such as OpenResty, then you can also use ffi to access C based time functions such as gettimeofday()
e.g: (Note: The pcall
check for the existence of struct timeval
is only necessary if you're running it repeatedly e.g. via content_by_lua_file
in OpenResty - without it you run into errors such as attempt to redefine 'timeval'
)
if pcall(ffi.typeof, "struct timeval") then
-- check if already defined.
else
-- undefined! let's define it!
ffi.cdef[[
typedef struct timeval {
long tv_sec;
long tv_usec;
} timeval;
int gettimeofday(struct timeval* t, void* tzp);
]]
end
local gettimeofday_struct = ffi.new("struct timeval")
local function gettimeofday()
ffi.C.gettimeofday(gettimeofday_struct, nil)
return tonumber(gettimeofday_struct.tv_sec) * 1000000 + tonumber(gettimeofday_struct.tv_usec)
end
Then the new lua gettimeofday()
function can be called from lua to provide the clock time to microsecond level accuracy.
Indeed, one could take a similar approaching using clock_gettime() to obtain nanosecond accuracy.
Upvotes: 5
Reputation: 2489
os.time()
return sec // only
https://luaposix.github.io/luaposix/modules/posix.time.html#clock_gettime
require'posix'.clock_gettime(0)
return sec, nsec
linux/time.h // man clock_gettime
/*
* The IDs of the various system clocks (for POSIX.1b interval timers):
*/
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
#define CLOCK_PROCESS_CPUTIME_ID 2
#define CLOCK_THREAD_CPUTIME_ID 3
#define CLOCK_MONOTONIC_RAW 4
#define CLOCK_REALTIME_COARSE 5
#define CLOCK_MONOTONIC_COARSE 6
http://w3.impa.br/~diego/software/luasocket/socket.html#gettime
require'socket'.gettime()
return sec.xxx
as waqas
says
get_millisecond.lua
local posix=require'posix'
local socket=require'socket'
for i=1,3 do
print( os.time() )
print( posix.clock_gettime(0) )
print( socket.gettime() )
print''
posix.nanosleep(0, 1) -- sec, nsec
end
output
lua get_millisecond.lua
1490186718
1490186718 268570540
1490186718.2686
1490186718
1490186718 268662191
1490186718.2687
1490186718
1490186718 268782765
1490186718.2688
Upvotes: 22
Reputation: 653
in openresty there is a function ngx.req.start_time.
From the docs:
Returns a floating-point number representing the timestamp (including milliseconds as the decimal part) when the current request was created.
Upvotes: 2
Reputation: 370
If you're using lua with nginx/openresty you could use ngx.now() which returns a float with millisecond precision
Upvotes: 9
Reputation: 121
I made a suitable solution for lua on Windows. I basically did what Kevlar suggested, but with a shared library rather than a DLL. This has been tested using cygwin.
I wrote some lua compatible C code, compiled it to a shared library (.so file via gcc in cygwin), and then loaded it up in lua using package.cpath and require" ". Wrote an adapter script for convenience. Here is all of the source:
first the C code, HighResTimer.c
////////////////////////////////////////////////////////////////
//HighResTimer.c by Cody Duncan
//
//compile with: gcc -o Timer.so -shared HighResTimer.c -llua5.1
//compiled in cygwin after installing lua (cant remember if I
// installed via setup or if I downloaded and compiled lua,
// probably the former)
////////////////////////////////////////////////////////////////
#include <windows.h>
typedef unsigned __int64 u64;
double mNanoSecondsPerCount;
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
int prevInit = 0;
int currInit = 0;
u64 prevTime = 0;
u64 currTime = 0;
u64 FrequencyCountPerSec;
LARGE_INTEGER frequencyTemp;
static int readHiResTimerFrequency(lua_State *L)
{
QueryPerformanceFrequency(&frequencyTemp);
FrequencyCountPerSec = frequencyTemp.QuadPart;
lua_pushnumber(L, frequencyTemp.QuadPart);
return 1;
}
LARGE_INTEGER timerTemp;
static int storeTime(lua_State *L)
{
QueryPerformanceCounter(&timerTemp);
if(!prevInit)
{
prevInit = 1;
prevTime = timerTemp.QuadPart;
}
else if (!currInit)
{
currInit = 1;
currTime = timerTemp.QuadPart;
}
else
{
prevTime = currTime;
currTime = timerTemp.QuadPart;
}
lua_pushnumber(L, timerTemp.QuadPart);
return 1;
}
static int getNanoElapsed(lua_State *L)
{
double mNanoSecondsPerCount = 1000000000/(double)FrequencyCountPerSec;
double elapsedNano = (currTime - prevTime)*mNanoSecondsPerCount;
lua_pushnumber(L, elapsedNano);
return 1;
}
int luaopen_HighResolutionTimer (lua_State *L) {
static const luaL_reg mylib [] =
{
{"readHiResTimerFrequency", readHiResTimerFrequency},
{"storeTime", storeTime},
{"getNanoElapsed", getNanoElapsed},
{NULL, NULL} /* sentinel */
};
luaL_register(L,"timer",mylib);
return 1;
}
Now lets get it loaded up in a lua script, HighResTimer.lua .
Note: I compiled the HighResTimer.c to a shared library, Timer.so
#!/bin/lua
------------------------------------
---HighResTimer.lua by Cody Duncan
---Wraps the High Resolution Timer Functions in
--- Timer.so
------------------------------------
package.cpath = "./Timer.so" --assuming Timer.so is in the same directory
require "HighResolutionTimer" --load up the module
timer.readHiResTimerFrequency(); --stores the tickFrequency
--call this before code that is being measured for execution time
function start()
timer.storeTime();
end
--call this after code that is being measured for execution time
function stop()
timer.storeTime();
end
--once the prior two functions have been called, call this to get the
--time elapsed between them in nanoseconds
function getNanosElapsed()
return timer.getNanoElapsed();
end
and Finally, utilize the timer, TimerTest.lua .
#!/bin/lua
------------------------------------
---TimerTest.lua by Cody Duncan
---
---HighResTimer.lua and Timer.so must
--- be in the same directory as
--- this script.
------------------------------------
require './HighResTimer'
start();
for i = 0, 3000000 do io.write("") end --do essentially nothing 3million times.
stop();
--divide nanoseconds by 1 million to get milliseconds
executionTime = getNanosElapsed()/1000000;
io.write("execution time: ", executionTime, "ms\n");
Note: Any comments were written after pasting the source code into the post editor, so technically this is untested, but hopefully the comments didn't befuddle anything. I will be sure to come back and provide a fix if it does.
Upvotes: 12
Reputation: 1463
If you want to benchmark, you can use os.clock as shown by the doc:
local x = os.clock()
local s = 0
for i=1,100000 do s = s + i end
print(string.format("elapsed time: %.2f\n", os.clock() - x))
Upvotes: 63
Reputation: 989
You can use C function gettimeofday : http://www.opengroup.org/onlinepubs/000095399/functions/gettimeofday.html
Here C library 'ul_time', function sec_usec resides in 'time' global table and returns seconds, useconds. Copy DLL to Lua folder, open it with require 'ul_time'.
http://depositfiles.com/files/3g2fx7dij
Upvotes: 0
Reputation: 10603
I use LuaSocket to get more precision.
require "socket"
print("Milliseconds: " .. socket.gettime()*1000)
This adds a dependency of course, but works fine for personal use (in benchmarking scripts for example).
Upvotes: 65
Reputation: 41220
Kevlar is correct.
An alternative to a custom DLL is Lua Alien
Upvotes: 2
Reputation: 8924
In standard C lua, no. You will have to settle for seconds, unless you are willing to modify the lua interpreter yourself to have os.time use the resolution you want. That may be unacceptable, however, if you are writing code for other people to run on their own and not something like a web application where you have full control of the environment.
Edit: another option is to write your own small DLL in C that extends lua with a new function that would give you the values you want, and require that dll be distributed with your code to whomever is going to be using it.
Upvotes: 39