有没有一种常用的方法可以以毫秒或毫秒为单位获取当前时间?
有os.time()
,但它只提供完整的秒数。
我使用 LuaSocket 来获得更高的精度。
require "socket"
print("Milliseconds: " .. socket.gettime()*1000)
这当然会增加一个依赖项,但可以很好地供个人使用(例如在基准测试脚本中)。
如果要进行基准测试,可以使用 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))
在标准 C lua 中,没有。您将不得不等待几秒钟,除非您愿意自己修改 lua 解释器以让 os.time 使用您想要的分辨率。但是,如果您正在编写代码供其他人自行运行,而不是像您可以完全控制环境的 Web 应用程序那样,这可能是不可接受的。
编辑:另一种选择是用 C 语言编写自己的小 DLL,该 DLL 使用新函数扩展 lua,该函数将为您提供所需的值,并要求将 dll 与您的代码一起分发给将要使用它的任何人。
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
正如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
我为 Windows 上的 lua 做了一个合适的解决方案。我基本上按照 Kevlar 的建议做了,但使用的是共享库而不是 DLL。这已使用 cygwin 进行了测试。
我编写了一些与 lua 兼容的 C 代码,将其编译为共享库(通过 cygwin 中的 gcc 的.so 文件),然后使用 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");
注意:任何评论都是在将源代码粘贴到帖子编辑器之后编写的,所以从技术上讲,这是未经测试的,但希望这些评论不会混淆任何东西。如果确实如此,我一定会回来并提供修复。
如果您将 lua 与 nginx/openresty 一起使用,则可以使用ngx.now()它返回毫秒精度的浮点数
如果您使用的是 OpenResty,那么它通过使用其ngx.now()函数提供了内置的毫秒时间精度。虽然如果你想要细粒度的毫秒精度,那么你可能需要先调用 ngx.update_time() 。或者,如果你想更进一步......
如果您使用的是启用了luajit的环境,例如 OpenResty,那么您还可以使用ffi访问基于 C 的时间函数,gettimeofday()
例如:(注意:仅当您重复运行它时才需要pcall
检查是否存在,例如通过in OpenResty - 没有它你会遇到错误,例如)struct timeval
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
然后gettimeofday()
可以从 lua 调用新的 lua 函数,以提供微秒级精度的时钟时间。
实际上,可以使用clock_gettime()采取类似的方法来获得纳秒级精度。
凯夫拉是正确的。
自定义 DLL 的替代方案是Lua Alien
您可以使用 C 函数 gettimeofday : http ://www.opengroup.org/onlinepubs/000095399/functions/gettimeofday.html
这里 C 库 'ul_time',函数 sec_usec 驻留在 'time' 全局表中并返回秒,u 秒。将 DLL 复制到 Lua 文件夹,使用 require 'ul_time' 打开它。
如果您的环境是 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 中)来关闭进程句柄:如果使用 5.4 之前的 Lua 版本并且担心资源耗尽,您可能希望将其扩展到三行,如Klesun 的 Windows -基于答案并明确关闭句柄。