Lua - Текущее время в миллисекундах

Есть ли общий способ получить текущее время в миллисекундах или с ними?

Существует os.time(), но он обеспечивает только полные секунды.

Ответ 1

В стандартном C lua, no. Вам придется успеть на несколько секунд, если вы не захотите самостоятельно модифицировать интерпретатор lua, чтобы использовать os.time нужное разрешение. Однако это может быть неприемлемым, если вы пишете код для других людей, чтобы работать самостоятельно, а не что-то вроде веб-приложения, где вы полностью контролируете среду.

Изменить: еще один вариант - написать собственную небольшую DLL в C, которая расширяет lua с помощью новой функции, которая даст вам нужные вам значения и потребует, чтобы DLL была распространена с вашим кодом тому, кто ее будет использовать.

Ответ 2

Я использую LuaSocket для получения большей точности.

require "socket"
print("Milliseconds: " .. socket.gettime()*1000)

Это, конечно, добавляет зависимость, но отлично работает для личного использования (например, в сценариях сравнения).

Ответ 3

Если вы хотите сравнить, вы можете использовать os.clock, как показано в документе:

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

Ответ 4

Я сделал подходящее решение для lua в Windows. Я в основном делал то, что предложил Кевлар, но с общей библиотекой, а не с DLL. Это было протестировано с использованием cygwin.

Я написал некоторый lua-совместимый C-код, скомпилировал его в общую библиотеку (.so файл через gcc в cygwin), а затем загрузил его в lua с помощью package.cpath и потребовал "". Написал адаптер script для удобства. Вот источник:

сначала код C, 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;
}

-

-

Теперь давайте загрузим его в lua script, HighResTimer.lua.

Примечание. Я скомпилировал HighResTimer.c в общей библиотеке, 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

-

-

и, наконец, используйте таймер 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");

Примечание. Любые комментарии были написаны после вставки исходного кода в редактор сообщений, поэтому технически это непроверено, но, надеюсь, комментарии ничего не путают. Я обязательно вернусь и дам исправление, если это произойдет.

Ответ 5

Получить текущее время в миллисекундах.

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

как говорит waqas


сравнить и проверить

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

выход

lua get_millisecond.lua
1490186718
1490186718      268570540
1490186718.2686

1490186718
1490186718      268662191
1490186718.2687

1490186718
1490186718      268782765
1490186718.2688

Ответ 6

Кевлар верен.

Альтернативой пользовательской DLL является Lua Alien

Ответ 7

Если вы используете lua с nginx/openresty, вы можете использовать ngx.now(), который возвращает поплавок с точностью до миллисекунды

Ответ 8

в openresty есть функция ngx.req.start_time.

Из документов:

Возвращает число с плавающей запятой, представляющее метку времени (включая миллисекунды как десятичную часть) при создании текущего запроса.

Ответ 10

Если вы используете среду с поддержкой luajit, такую как OpenResty, то вы можете использовать ffi для доступа к функциям времени на основе C, таким как gettimeofday() например: (Примечание: проверка pcall на наличие struct timeval необходима, только если вы выполняете это неоднократно, например, через content_by_lua_file в OpenResty - без этого вы столкнетесь с ошибками, такими как attempt to redefine 'timeval')

if pcall(ffi.typeof, "struct timeval") then
        -- check if already defined.
else
        -- undefined! let 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

Затем новая gettimeofday() lua gettimeofday() может быть вызвана из lua для обеспечения точности часов с точностью до микросекундного уровня.