92

Is there a common way to get the current time in or with milliseconds?

There is os.time(), but it only provides full seconds.

0

12 Answers 12

65

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).

Sign up to request clarification or add additional context in comments.

2 Comments

Note that at least one person claims that on Windows this implementation is not high-resolution enough: lua-users.org/wiki/HiResTimer
Note that on my system after an update, this stopped working. I had to change it to socket = require "socket", as otherwise socket was nil.
64

If you want to benchmark, you can use os.clock as in the official docs:

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))

8 Comments

Rather than milliseconds however, this appears to work with a precision of 1/100 s.
@schaul That seems untrue to me (Lua 5.5 compiled with MSVC on Windows 11.) Executing time_ms = select(2, math.modf(os.clock())) * 1000.0 I regularly see 3-digit numbers with diverse nonzero unit-place elements. How did you come to your conclusion?
and this does not work well if you have a call to a C function which uses threads. instead of the actual time taken, it reports the time taken by all threads, as a sum
This function as well as the os.time function are highly system-dependent. Also note that documentation states that it returns the cpu time used by the program, which on most systems is very different from the actual "earth-time" spent.
Since I'm stuck with standard Lua and it must be portable and encapsulated (no external dll), this is the best solution I can find. +1
@ShaneBishop see lua.org/pil/22.1.html at the bottom of the page
|
40

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.

3 Comments

DLL or .so, etc. Depends on system... :-)
What are the decimals returned in os.clock()?
@Kousha the decimals in os.clock are fractions of a second; however, os.clock reports program execution time not real world time. os.clock is also inconsistent arcoss platforms as it reports real time vs cpu time on Windows systems.
22

Get current time in milliseconds.

os.time()

os.time()
return sec // only

posix.clock_gettime(clk)

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

socket.gettime()

http://w3.impa.br/~diego/software/luasocket/socket.html#gettime

require'socket'.gettime()
return sec.xxx

as waqas says


compare & test

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

Comments

12

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.

6 Comments

Useful! If anyone wants to port this to mac or linux, you could use the high resolution C code here: github.com/tylerneylon/oswrap/blob/master/oswrap_mac/now.c
@Tyler: And how would you go about calling that from lua?
@SuperJedi224 You'd have to create a C wrapper, something like int getHighResTime(lua_State *L) { /* push the time onto the lua stack */ return 1; }, add code to register the C fns with Lua, and then compile that with the Lua C API as a shared library. Here's a decent pdf on that process: cs.brynmawr.edu/Courses/cs380/fall2011/luar-topics2.pdf
I'd also avoid wiping out the existing package.cpath; instead I'd prepend to it with package.cpath = "./Timer.so;" .. package.cpath...
On Windows, you can call the sys.clock() function from LuaRT.
|
9

If you're using lua with nginx/openresty you could use ngx.now() which returns a float with millisecond precision

6 Comments

this is wrong github.com/openresty/lua-nginx-module#ngxnow from the docs: "Returns a floating-point number for the elapsed time in seconds (including milliseconds as the decimal part) from the epoch for the current time stamp from the nginx cached time (no syscall involved unlike Lua's date library)."
You're really impolite. You can't affirm what I wrote is "wrong". I only suggested a possible solution (that I used for a load test and it worked perfectly), and I linked the documentation (so whoever interested in that could check the details).
Moreover if you take a look at the sources, ngx.req.start_time that you're suggesting uses cached time too (ngx_timeofday). Therefore you'll probably get the same result of ngx.now or earlier.
Sorry i was up for being impolite. I truly apologize. But if i understand it correctly, ngx.now() returns the timestamp from when the request been started + the time the current script was running until you actually call ngx.now()
No, it's an epoch timestamp. Both ngx.now() and ngx.req.start_time() internally use ngx_timeofday(), which is the nginx cached time (which is updated frequently though). Therefore it may happen that both functions return the same value, or most probably different values close to each other.
|
5

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.

Comments

3

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.

Comments

2

Kevlar is correct.

An alternative to a custom DLL is Lua Alien

Comments

2

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.

1 Comment

Unfortunately in my case ngx.req.start_time() returns 0. Same as os.clock() btw. Openresty ver. I'm using: "openresty/1.13.6.2"
1

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().

1 Comment

I wouldn't recommend trying to combine numbers from two separate timestamps: that's liable to cause jumps if the time rolls over between the two, eg. if the io.popen call runs at 12:34:56.99 and the os.time call runs at 12:34:57.00 (or vice versa).
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.