現在の時刻をミリ秒単位で取得する一般的な方法はありますか?
ありますが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 では、いいえ。os.time が必要な解像度を使用するように自分で lua インタープリターを変更する意思がない限り、数秒で解決する必要があります。ただし、環境を完全に制御できる Web アプリケーションのようなものではなく、他の人が自分で実行するコードを作成している場合、これは受け入れられない可能性があります。
編集:別のオプションは、必要な値を提供する新しい関数で lua を拡張する独自の小さな DLL を C で記述し、それを使用する人にコードと共に dll を配布することを要求することです。
Windows上のluaに適したソリューションを作成しました。私は基本的に Kevlar が提案したことを行いましたが、DLL ではなく共有ライブラリを使用しました。これは cygwin を使用してテストされています。
lua 互換の C コードを書き、それを共有ライブラリ (cygwin の gcc を介して .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");
注: ソース コードを投稿エディターに貼り付けた後にコメントが書き込まれたため、技術的にはテストされていませんが、コメントが混乱しないことを願っています。もしそうなら、私は必ず戻ってきて修正を提供します。
nginx/openresty で lua を使用している場合は、ミリ秒の精度で float を返すngx.now()を使用できます
ケブラーは正しいです。
カスタム DLL の代替はLua Alienです
openresty には関数ngx.req.start_timeがあります。
ドキュメントから:
現在のリクエストが作成されたときのタイムスタンプ (小数部としてミリ秒を含む) を表す浮動小数点数を返します。
C 関数 gettimeofday を使用できます: http://www.opengroup.org/onlinepubs/000095399/functions/gettimeofday.html
ここで C ライブラリ 'ul_time'、関数 sec_usec は 'time' グローバル テーブルに存在し、秒、useconds を返します。DLL を Lua フォルダーにコピーし、require 'ul_time' で開きます。