Lua-以毫秒为单位的当前时间

有没有一种通用的方法来获取当前时间的毫秒数或毫秒数?

os.time(),但它只提供完整的秒。

160174 次浏览

在标准 C Lua 中,没有。除非您愿意自己修改 lua 解释器,让 os.time 使用您想要的分辨率,否则您将不得不满足于几秒钟。但是,如果您编写的代码是为了让其他人自己运行,而不是像 Web 应用程序那样完全控制环境,那么这可能是不可接受的。

编辑: 另一种选择是用 C 语言编写自己的小 DLL,用一个新函数扩展 lua,这个函数将提供您想要的值,并要求 DLL 与您的代码一起分发给将要使用它的任何人。

防弹衣是对的。

自定义 DLL 的另一种选择是 Lua Alien

我使用 LuaSocket 来获得更高的精度。

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

这当然增加了一个依赖项,但是对于个人使用(例如在基准测试脚本中)很有效。

你可以使用 C 函数 gettimeofday: Http://www.opengroup.org/onlinepubs/000095399/functions/gettimeofday.html

在这里,C 库‘ ul _ time’函数 sec _ usec 驻留在‘ time’全局表中,并返回秒、秒。将 DLL 复制到 Lua 文件夹,打开时需要输入“ ul _ time”。

Http://depositfiles.com/files/3g2fx7dij

如果你想做基准测试,你可以使用 os.lock,如文档所示:

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

我做了一个合适的解决方案,在视窗 lua。我基本上按照凯夫拉尔的建议做了,但使用的是共享库,而不是 DLL。这已经用 Cygwin 测试过了。

我编写了一些 lua 兼容的 C 代码,并将其编译为一个共享库(。所以通过 cygwin 中的 gcc 文件) ,然后使用 package.cpath 在 lua 中加载它,并要求“”。为方便起见,编写了一个适配器脚本。下面是所有的资料来源:

首先是 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 脚本 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");

注意: 任何注释都是在将源代码粘贴到后期编辑器之后编写的,所以从技术上讲,这是未经测试的,但希望注释不会让任何东西感到困惑。如果真的发生了,我一定会回来修复的。

如果在 nginx/openresty 中使用 lua,可以使用 Now (),它返回毫秒精度的浮点数

在 openresty 中有一个函数 Start _ time

来自文件:

返回一个浮点数,表示创建当前请求时的时间戳(包括作为小数部分的毫秒)。

获取以毫秒为单位的当前时间。

时间()

os.time()
return sec // only

Lock _ 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

Gettime ()

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

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

就像 waqas说的


比较和测试

得到 _ 毫秒。 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

如果您正在使用 OpenResty,那么它通过使用其 Now ()函数提供内置的毫秒时间精度。尽管如果希望获得细粒度的毫秒精度,那么可能需要首先调用 ngx.update _ time ()。或者如果你想更进一步..。

如果你使用的是启用了 Luajit的环境,比如 OpenResty,那么你也可以使用 Fi来访问基于 C 的时间函数,比如 gettimeofday()。(注意: pcall检查是否存在 struct timeval只有在你重复运行它的情况下才是必要的,比如在 OpenResty 中通过 content_by_lua_file运行——如果没有它,你就会遇到像 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

然后可以从 lua 调用新的 lua gettimeofday()函数来提供时钟时间到 微秒级的精度。

事实上,人们可以采取类似的接近使用 Lock _ gettime ()获得 毫微秒的准确性。

如果您的环境是 Windows,并且您可以访问系统命令,那么您可以使用 io.popen(command)获得厘秒的精度:

local handle = io.popen("echo %time%")
local result = handle:read("*a")
handle:close()

结果将包含 hh:mm:ss.cc格式的字符串: (带有尾行分隔符)

"19:56:53.90\n"

注意,它位于本地时区,因此您可能只想提取 .cc部分,并将其与 os.time()的纪元秒组合起来。

如果您所在的系统具有与 GNU 兼容的 date实现,并且您可以执行该实现,那么下面的一行程序可以获得以毫秒为单位的 Epoch 时间:

local function gethammertime()
return tonumber(assert(assert(io.popen'date +%s%3N'):read'a'))
end

请注意,需要使用 assert调用来确保任何读取或打开 date的失败都将分别传播这些错误。还要注意,这依赖于垃圾收集(或终结器,在 Lua 5.4中)来关闭进程句柄: 如果使用 Lua 的前5.4版本和资源耗尽是一个问题,您可能希望将其扩展到三行,如 Klesun 基于 Windows 的答案,并显式关闭句柄。