123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <errno.h>
- #include <unistd.h>
- #include <dlfcn.h>
- #if __APPLE__
- #include <mach/mach_time.h>
- #endif
- #include <lua.h>
- #include <lualib.h>
- #include <lauxlib.h>
- #include "timeout.h"
- #include "bench.h"
- #if LUA_VERSION_NUM < 502
- static int lua_absindex(lua_State *L, int idx) {
- return (idx > 0 || idx <= LUA_REGISTRYINDEX)? idx : lua_gettop(L) + idx + 1;
- } /* lua_absindex() */
- static void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
- int i, t = lua_absindex(L, -1 - nup);
- for (; l->name; l++) {
- for (i = 0; i < nup; i++)
- lua_pushvalue(L, -nup);
- lua_pushcclosure(L, l->func, nup);
- lua_setfield(L, t, l->name);
- }
- lua_pop(L, nup);
- } /* luaL_setfuncs() */
- #define luaL_newlibtable(L, l) \
- lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1)
- #define luaL_newlib(L, l) \
- (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0))
- #endif
- #ifndef MAX
- #define MAX(a, b) (((a) > (b))? (a) : (b))
- #endif
- struct bench {
- const char *path;
- void *solib;
- size_t count;
- timeout_t timeout_max;
- int verbose;
- void *state;
- struct timeout *timeout;
- struct benchops ops;
- timeout_t curtime;
- }; /* struct bench */
- #if __APPLE__
- static mach_timebase_info_data_t timebase;
- #endif
- static int long long monotime(void) {
- #if __APPLE__
- unsigned long long abt;
- abt = mach_absolute_time();
- abt = abt * timebase.numer / timebase.denom;
- return abt / 1000LL;
- #else
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return (ts.tv_sec * 1000000L) + (ts.tv_nsec / 1000L);
- #endif
- } /* monotime() */
- static int bench_clock(lua_State *L) {
- lua_pushnumber(L, (double)monotime() / 1000000L);
- return 1;
- } /* bench_clock() */
- static int bench_new(lua_State *L) {
- const char *path = luaL_checkstring(L, 1);
- size_t count = luaL_optinteger(L, 2, 1000000);
- timeout_t timeout_max = luaL_optinteger(L, 3, 300 * 1000000L);
- int verbose = (lua_isnone(L, 4))? 0 : lua_toboolean(L, 4);
- struct bench *B;
- struct benchops *ops;
- B = lua_newuserdata(L, sizeof *B);
- memset(B, 0, sizeof *B);
- luaL_getmetatable(L, "BENCH*");
- lua_setmetatable(L, -2);
- B->count = count;
- B->timeout_max = timeout_max;
- B->verbose = verbose;
- if (!(B->timeout = calloc(count, sizeof *B->timeout)))
- return luaL_error(L, "%s", strerror(errno));
- if (!(B->solib = dlopen(path, RTLD_NOW|RTLD_LOCAL)))
- return luaL_error(L, "%s: %s", path, dlerror());
- if (!(ops = dlsym(B->solib, "benchops")))
- return luaL_error(L, "%s: %s", path, dlerror());
- B->ops = *ops;
- B->state = B->ops.init(B->timeout, B->count, B->verbose);
- return 1;
- } /* bench_new() */
- static int bench_add(lua_State *L) {
- struct bench *B = lua_touserdata(L, 1);
- unsigned i;
- timeout_t t;
- i = (lua_isnoneornil(L, 2))? random() % B->count : (unsigned)luaL_checkinteger(L, 2);
- t = (lua_isnoneornil(L, 3))? random() % B->timeout_max : (unsigned)luaL_checkinteger(L, 3);
- B->ops.add(B->state, &B->timeout[i], t);
- return 0;
- } /* bench_add() */
- static int bench_del(lua_State *L) {
- struct bench *B = lua_touserdata(L, 1);
- size_t i = luaL_optinteger(L, 2, random() % B->count);
- size_t j = luaL_optinteger(L, 3, i);
- while (i <= j && i < B->count) {
- B->ops.del(B->state, &B->timeout[i]);
- ++i;
- }
- return 0;
- } /* bench_del() */
- static int bench_fill(lua_State *L) {
- struct bench *B = lua_touserdata(L, 1);
- size_t count = luaL_optinteger(L, 2, B->count);
- long timeout_inc = luaL_optinteger(L, 3, -1), timeout_max = 0, timeout;
- size_t i;
- if (timeout_inc < 0) {
- for (i = 0; i < count; i++) {
- timeout = random() % B->timeout_max;
- B->ops.add(B->state, &B->timeout[i], timeout);
- timeout_max = MAX(timeout, timeout_max);
- }
- } else {
- for (i = 0; i < count; i++) {
- timeout = timeout_inc + i;
- B->ops.add(B->state, &B->timeout[i], timeout_inc + i);
- timeout_max = MAX(timeout, timeout_max);
- }
- }
- lua_pushinteger(L, (lua_Integer)count);
- lua_pushinteger(L, (lua_Integer)timeout_max);
- return 2;
- } /* bench_fill() */
- static int bench_expire(lua_State *L) {
- struct bench *B = lua_touserdata(L, 1);
- unsigned count = luaL_optinteger(L, 2, B->count);
- unsigned step = luaL_optinteger(L, 3, 300000);
- size_t i = 0;
- while (i < count && !B->ops.empty(B->state)) {
- B->curtime += step;
- B->ops.update(B->state, B->curtime);
- while (B->ops.get(B->state))
- i++;
- }
- lua_pushinteger(L, (lua_Integer)i);
- return 1;
- } /* bench_expire() */
- static int bench_empty(lua_State *L) {
- struct bench *B = lua_touserdata(L, 1);
- lua_pushboolean(L, B->ops.empty(B->state));
- return 1;
- } /* bench_empty() */
- static int bench__next(lua_State *L) {
- struct bench *B = lua_touserdata(L, lua_upvalueindex(1));
- struct timeouts_it *it = lua_touserdata(L, lua_upvalueindex(2));
- struct timeout *to;
- if (!B->ops.next || !(to = B->ops.next(B->state, it)))
- return 0;
- lua_pushinteger(L, luaL_optinteger(L, 2, 0) + 1);
- lua_newtable(L);
- lua_pushinteger(L, to->expires);
- lua_setfield(L, -2, "expires");
- return 2;
- } /* bench__next() */
- static int bench__pairs(lua_State *L) {
- struct timeouts_it *it;
- lua_settop(L, 1);
- it = lua_newuserdata(L, sizeof *it);
- TIMEOUTS_IT_INIT(it, TIMEOUTS_ALL);
- lua_pushcclosure(L, &bench__next, 2);
- lua_pushvalue(L, 1);
- lua_pushinteger(L, 0);
- return 3;
- } /* bench__pairs() */
- static int bench__gc(lua_State *L) {
- struct bench *B = lua_touserdata(L, 1);
- if (B->state) {
- B->ops.destroy(B->state);
- B->state = NULL;
- }
- return 0;
- } /* bench__gc() */
- static const luaL_Reg bench_methods[] = {
- { "add", &bench_add },
- { "del", &bench_del },
- { "fill", &bench_fill },
- { "expire", &bench_expire },
- { "empty", &bench_empty },
- { "close", &bench__gc },
- { NULL, NULL }
- };
- static const luaL_Reg bench_metatable[] = {
- { "__pairs", &bench__pairs },
- { "__gc", &bench__gc },
- { NULL, NULL }
- };
- static const luaL_Reg bench_globals[] = {
- { "new", &bench_new },
- { "clock", &bench_clock },
- { NULL, NULL }
- };
- int luaopen_bench(lua_State *L) {
- #if __APPLE__
- mach_timebase_info(&timebase);
- #endif
- if (luaL_newmetatable(L, "BENCH*")) {
- luaL_setfuncs(L, bench_metatable, 0);
- luaL_newlib(L, bench_methods);
- lua_setfield(L, -2, "__index");
- }
- luaL_newlib(L, bench_globals);
- return 1;
- } /* luaopen_bench() */
|