9 #include <mach/mach_time.h>
19 #if LUA_VERSION_NUM < 502
20 static int lua_absindex(lua_State *L,
int idx) {
21 return (idx > 0 || idx <= LUA_REGISTRYINDEX)? idx : lua_gettop(L) + idx + 1;
24 static void luaL_setfuncs(lua_State *L,
const luaL_Reg *l,
int nup) {
25 int i, t = lua_absindex(L, -1 - nup);
27 for (; l->name; l++) {
28 for (i = 0; i < nup; i++)
29 lua_pushvalue(L, -nup);
30 lua_pushcclosure(L, l->func, nup);
31 lua_setfield(L, t, l->name);
37 #define luaL_newlibtable(L, l) \
38 lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1)
40 #define luaL_newlib(L, l) \
41 (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0))
45 #define MAX(a, b) (((a) > (b))? (a) : (b))
53 timeout_t timeout_max;
64 static mach_timebase_info_data_t timebase;
68 static int long long monotime(
void) {
70 unsigned long long abt;
72 abt = mach_absolute_time();
73 abt = abt * timebase.numer / timebase.denom;
79 clock_gettime(CLOCK_MONOTONIC, &ts);
81 return (ts.tv_sec * 1000000L) + (ts.tv_nsec / 1000L);
86 static int bench_clock(lua_State *L) {
87 lua_pushnumber(L, (
double)monotime() / 1000000L);
93 static int bench_new(lua_State *L) {
94 const char *path = luaL_checkstring(L, 1);
95 size_t count = luaL_optinteger(L, 2, 1000000);
96 timeout_t timeout_max = luaL_optinteger(L, 3, 300 * 1000000L);
97 int verbose = (lua_isnone(L, 4))? 0 : lua_toboolean(L, 4);
101 B = lua_newuserdata(L,
sizeof *B);
102 memset(B, 0,
sizeof *B);
104 luaL_getmetatable(L,
"BENCH*");
105 lua_setmetatable(L, -2);
108 B->timeout_max = timeout_max;
109 B->verbose = verbose;
111 if (!(B->timeout = calloc(count,
sizeof *B->timeout)))
112 return luaL_error(L,
"%s", strerror(errno));
114 if (!(B->solib = dlopen(path, RTLD_NOW|RTLD_LOCAL)))
115 return luaL_error(L,
"%s: %s", path, dlerror());
117 if (!(ops = dlsym(B->solib,
"benchops")))
118 return luaL_error(L,
"%s: %s", path, dlerror());
121 B->state = B->ops.init(B->timeout, B->count, B->verbose);
127 static int bench_add(lua_State *L) {
128 struct bench *B = lua_touserdata(L, 1);
132 i = (lua_isnoneornil(L, 2))? random() % B->count : (unsigned)luaL_checkinteger(L, 2);
133 t = (lua_isnoneornil(L, 3))? random() % B->timeout_max : (unsigned)luaL_checkinteger(L, 3);
135 B->ops.add(B->state, &B->timeout[i], t);
141 static int bench_del(lua_State *L) {
142 struct bench *B = lua_touserdata(L, 1);
143 size_t i = luaL_optinteger(L, 2, random() % B->count);
144 size_t j = luaL_optinteger(L, 3, i);
146 while (i <= j && i < B->count) {
147 B->ops.del(B->state, &B->timeout[i]);
155 static int bench_fill(lua_State *L) {
156 struct bench *B = lua_touserdata(L, 1);
157 size_t count = luaL_optinteger(L, 2, B->count);
158 long timeout_inc = luaL_optinteger(L, 3, -1), timeout_max = 0,
timeout;
161 if (timeout_inc < 0) {
162 for (i = 0; i < count; i++) {
163 timeout = random() % B->timeout_max;
164 B->ops.add(B->state, &B->timeout[i],
timeout);
168 for (i = 0; i < count; i++) {
170 B->ops.add(B->state, &B->timeout[i], timeout_inc + i);
175 lua_pushinteger(L, (lua_Integer)count);
176 lua_pushinteger(L, (lua_Integer)timeout_max);
182 static int bench_expire(lua_State *L) {
183 struct bench *B = lua_touserdata(L, 1);
184 unsigned count = luaL_optinteger(L, 2, B->count);
185 unsigned step = luaL_optinteger(L, 3, 300000);
188 while (i < count && !B->ops.empty(B->state)) {
190 B->ops.update(B->state, B->curtime);
192 while (B->ops.get(B->state))
196 lua_pushinteger(L, (lua_Integer)i);
202 static int bench_empty(lua_State *L) {
203 struct bench *B = lua_touserdata(L, 1);
205 lua_pushboolean(L, B->ops.empty(B->state));
211 static int bench__next(lua_State *L) {
212 struct bench *B = lua_touserdata(L, lua_upvalueindex(1));
213 struct timeouts_it *it = lua_touserdata(L, lua_upvalueindex(2));
216 if (!B->ops.next || !(to = B->ops.next(B->state, it)))
219 lua_pushinteger(L, luaL_optinteger(L, 2, 0) + 1);
222 lua_pushinteger(L, to->expires);
223 lua_setfield(L, -2,
"expires");
228 static int bench__pairs(lua_State *L) {
233 it = lua_newuserdata(L,
sizeof *it);
234 TIMEOUTS_IT_INIT(it, TIMEOUTS_ALL);
236 lua_pushcclosure(L, &bench__next, 2);
238 lua_pushinteger(L, 0);
244 static int bench__gc(lua_State *L) {
245 struct bench *B = lua_touserdata(L, 1);
248 B->ops.destroy(B->state);
256 static const luaL_Reg bench_methods[] = {
257 {
"add", &bench_add },
258 {
"del", &bench_del },
259 {
"fill", &bench_fill },
260 {
"expire", &bench_expire },
261 {
"empty", &bench_empty },
262 {
"close", &bench__gc },
266 static const luaL_Reg bench_metatable[] = {
267 {
"__pairs", &bench__pairs },
268 {
"__gc", &bench__gc },
272 static const luaL_Reg bench_globals[] = {
273 {
"new", &bench_new },
274 {
"clock", &bench_clock },
278 int luaopen_bench(lua_State *L) {
280 mach_timebase_info(&timebase);
283 if (luaL_newmetatable(L,
"BENCH*")) {
284 luaL_setfuncs(L, bench_metatable, 0);
285 luaL_newlib(L, bench_methods);
286 lua_setfield(L, -2,
"__index");
289 luaL_newlib(L, bench_globals);
Definitions for timing-related constants.