有没有一种常见的方法可以获取当前时间(包括毫秒)?
虽然有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))
os.time
函数高度依赖于系统。还要注意文档中说明它返回程序使用的CPU时间,在大多数系统上与实际花费的"地球时间"非常不同。 - dualedos.clock()
返回的是什么小数? - Koushaos.clock
中的小数是秒的分数;但是,os.clock
报告的是程序执行时间而不是真实世界时间。在 Windows 系统上,os.clock
还不一致地报告 real time
和 cpu time
。 - Nifimos.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代码,使用gcc在cygwin中将其编译为共享库(.so文件),然后使用package.cpath和require" "在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");
注意:任何评论都是在将源代码粘贴到文章编辑器后编写的,因此从技术上讲,这是未经测试的,但希望这些评论不会对任何事情造成困扰。如果有问题,我一定会回来提供修复方案。
int getHighResTime(lua_State *L) { /* 将时间推入lua堆栈 */ return 1; }
,添加代码以在Lua中注册C函数,然后使用Lua C API将其编译为共享库。这是一个不错的关于该过程的PDF文档:http://cs.brynmawr.edu/Courses/cs380/fall2011/luar-topics2.pdf - Tylerpackage.cpath
;相反,我会使用 package.cpath = "./Timer.so;" .. package.cpath
来将其前置。 - SlySvengettimeofday()
,例如:(注意: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
gettimeofday()
函数可以从lua中调用,提供时钟时间到微秒级精度。实际上,使用clock_gettime()采取类似方法,可以获得纳秒精度。date
实现,那么以下是获取毫秒级别的Epoch时间的一行代码:local function gethammertime()
return tonumber(assert(assert(io.popen'date +%s%3N'):read'a'))
end
assert
调用是必要的,以确保任何读取或打开 date
的失败都会相应地传播错误。还要注意,这依赖于垃圾回收(或 Lua 5.4 中的 finalizers)来关闭进程句柄:如果使用早于 Lua 5.4 的版本并且资源耗尽是一个问题,则可能希望将其扩展为三行,如 Klesun's Windows-based answer 并显式关闭句柄。
socket = require "socket"
,否则socket
将为空值。 - phemmer