web-dev-qa-db-ja.com

Lua-ミリ秒単位の現在の時間

現在の時刻をミリ秒単位で取得する一般的な方法はありますか?

os.time()がありますが、完全な秒数のみを提供します。

67
okoman

標準C luaでは、ありません。 os.timeが希望する解像度を使用するように自分でluaインタープリターを変更する場合を除き、数秒間解決する必要があります。しかし、環境を完全に制御できるWebアプリケーションのようなものではなく、他の人が自分で実行するためのコードを書いている場合、これは受け入れられないかもしれません。

編集:別のオプションは、あなた自身の小さなDLLをCで書くことです。これは、あなたが望む値を与える新しい関数でluaを拡張します。それを使用するつもりです。

33
Kevlar

LuaSocketを使用して、精度を高めます。

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

これはもちろん依存関係を追加しますが、個人使用(たとえば、スクリプトのベンチマーク)には正常に機能します。

58
waqas

ベンチマークを行いたい場合は、ドキュメントに示されている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))
52

Windows上のluaに適したソリューションを作成しました。基本的にケブラーが提案したことを行いましたが、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");

注:コメントはソースコードをポストエディターに貼り付けた後に記述されているため、技術的にはテストされていませんが、コメントが何の混乱ももたらさないことを願っています。修正された場合は、必ず戻って修正を提供します。

10
Cody Duncan

現在の時間をミリ秒で取得します。

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
8
yurenchen

ケブラーは正しいです。

カスタムDLLの代替手段は Lua Alien

3
Doug Currie

Nginx/openrestyでluaを使用している場合は、 ngx.now() を使用して、ミリ秒の精度で浮動小数点数を返します。

3
deepskyblue86

openrestyには、関数 ngx.req.start_time があります。

ドキュメントから:

現在の要求が作成されたときのタイムスタンプ(小数部のミリ秒を含む)を表す浮動小数点数を返します。

2
smartius

OpenRestyなどの luajit 有効な環境を使用している場合、 ffi を使用してgettimeofday()などのCベースの時間関数にアクセスできます。例:(注:struct timevalの存在のpcallチェックは、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 gettimeofday()関数をluaから呼び出して、クロック時間をmicrosecondレベルの精度で提供できます。

0
Pierz

C関数gettimeofdayを使用できます: http://www.opengroup.org/onlinepubs/000095399/functions/gettimeofday.html

ここで、Cライブラリ「ul_time」、関数sec_usecは「time」グローバルテーブルにあり、秒、usecondsを返します。 LuaフォルダーにDLLをコピーし、 'ul_time'を要求してそれを開きます。

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

0
qwer