Existe-t-il un moyen courant d'obtenir l'heure actuelle en ou avec des millisecondes?
Il y a os.time()
, mais il ne fournit que des secondes entières.
Dans la norme C lua, non. Vous devrez vous contenter de quelques secondes, à moins que vous ne souhaitiez modifier vous-même l'interpréteur lua pour que os.time utilise la résolution souhaitée. Cela peut être inacceptable, cependant, si vous écrivez du code pour que d'autres personnes s'exécutent de leur propre chef et non quelque chose comme une application Web où vous avez le contrôle total de l'environnement.
Edit: une autre option est d'écrire votre propre petit DLL en C qui étend lua avec une nouvelle fonction qui vous donnerait les valeurs que vous voulez, et exigerait que la DLL soit distribuée avec votre code à quiconque est va l'utiliser.
J'utilise LuaSocket pour obtenir plus de précision.
require "socket"
print("Milliseconds: " .. socket.gettime()*1000)
Cela ajoute une dépendance bien sûr, mais fonctionne très bien pour un usage personnel (dans les scripts de benchmarking par exemple).
Si vous voulez comparer, vous pouvez utiliser os.clock comme indiqué dans le document:
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))
J'ai fait une solution appropriée pour lua sur Windows. J'ai essentiellement fait ce que Kevlar a suggéré, mais avec une bibliothèque partagée plutôt qu'avec une DLL. Cela a été testé avec cygwin.
J'ai écrit du code C compatible avec lua, je l'ai compilé dans une bibliothèque partagée (fichier .so via gcc dans cygwin), puis je l'ai chargé dans lua en utilisant package.cpath et j'ai besoin de "". A écrit un script d'adaptateur pour plus de commodité. Voici toute la source:
d'abord le code 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;
}
Permet maintenant de le charger dans un script lua, HighResTimer.lua.
Remarque: j'ai compilé le HighResTimer.c dans une bibliothèque partagée, 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
et enfin, utilisez la minuterie, 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");
Remarque: Tous les commentaires ont été écrits après avoir collé le code source dans l'éditeur de publication, donc techniquement, cela n'a pas été testé, mais j'espère que les commentaires n'ont rien dérouté. Je serai sûr de revenir et de fournir un correctif si c'est le cas.
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
comme le dit 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
sortie
lua get_millisecond.lua
1490186718
1490186718 268570540
1490186718.2686
1490186718
1490186718 268662191
1490186718.2687
1490186718
1490186718 268782765
1490186718.2688
Le kevlar est correct.
Une alternative à un personnalisé DLL est Lua Alien
Si vous utilisez lua avec nginx/openresty, vous pouvez utiliser ngx.now () qui retourne un flottant avec une précision en millisecondes
dans openresty il y a une fonction ngx.req.start_time .
De la documentation:
Renvoie un nombre à virgule flottante représentant l'horodatage (y compris les millisecondes comme partie décimale) lorsque la demande en cours a été créée.
Si vous utilisez un environnement activé par luajit comme OpenResty, vous pouvez utiliser ffi pour accéder aux fonctions de temps basées sur C telles que gettimeofday()
par exemple: (Remarque : La vérification de pcall
pour l'existence de struct timeval
N'est nécessaire que si vous l'exécutez à plusieurs reprises, par exemple via content_by_lua_file
Dans OpenResty - sans cela, vous rencontrez des erreurs telles que 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
Ensuite, la nouvelle fonction lua gettimeofday()
peut être appelée à partir de lua pour fournir le temps d'horloge avec une précision de niveau microseconde .
Vous pouvez utiliser la fonction C gettimeofday: http://www.opengroup.org/onlinepubs/000095399/functions/gettimeofday.html
Ici, la bibliothèque C 'ul_time', la fonction sec_usec réside dans la table globale 'time' et renvoie les secondes, les secondes d'utilisation. Copiez DLL dans le dossier Lua, ouvrez-le avec require 'ul_time'.