tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

bench.c (6255B)


      1 #include <stdlib.h>
      2 #include <string.h>
      3 #include <time.h>
      4 #include <errno.h>
      5 #include <unistd.h>
      6 #include <dlfcn.h>
      7 
      8 #if __APPLE__
      9 #include <mach/mach_time.h>
     10 #endif
     11 
     12 #include <lua.h>
     13 #include <lualib.h>
     14 #include <lauxlib.h>
     15 
     16 #include "timeout.h"
     17 #include "bench.h"
     18 
     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;
     22 } /* lua_absindex() */
     23 
     24 static void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
     25 int i, t = lua_absindex(L, -1 - nup);
     26 
     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);
     32 }
     33 
     34 lua_pop(L, nup);
     35 } /* luaL_setfuncs() */
     36 
     37 #define luaL_newlibtable(L, l) \
     38 lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1)
     39 
     40 #define luaL_newlib(L, l) \
     41 (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0))
     42 #endif
     43 
     44 #ifndef MAX
     45 #define MAX(a, b) (((a) > (b))? (a) : (b))
     46 #endif
     47 
     48 
     49 struct bench {
     50 const char *path;
     51 void *solib;
     52 size_t count;
     53 timeout_t timeout_max;
     54 int verbose;
     55 
     56 void *state;
     57 struct timeout *timeout;
     58 struct benchops ops;
     59 timeout_t curtime;
     60 }; /* struct bench */
     61 
     62 
     63 #if __APPLE__
     64 static mach_timebase_info_data_t timebase;
     65 #endif
     66 
     67 
     68 static int long long monotime(void) {
     69 #if __APPLE__
     70 unsigned long long abt;
     71 
     72 abt = mach_absolute_time();
     73 abt = abt * timebase.numer / timebase.denom;
     74 
     75 return abt / 1000LL;
     76 #else
     77 struct timespec ts;
     78 
     79 clock_gettime(CLOCK_MONOTONIC, &ts);
     80 
     81 return (ts.tv_sec * 1000000L) + (ts.tv_nsec / 1000L);
     82 #endif
     83 } /* monotime() */
     84 
     85 
     86 static int bench_clock(lua_State *L) {
     87 lua_pushnumber(L, (double)monotime() / 1000000L);
     88 
     89 return 1;
     90 } /* bench_clock() */
     91 
     92 
     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);
     98 struct bench *B;
     99 struct benchops *ops;
    100 
    101 B = lua_newuserdata(L, sizeof *B);
    102 memset(B, 0, sizeof *B);
    103 
    104 luaL_getmetatable(L, "BENCH*");
    105 lua_setmetatable(L, -2);
    106 
    107 B->count = count;
    108 B->timeout_max = timeout_max;
    109 B->verbose = verbose;
    110 
    111 if (!(B->timeout = calloc(count, sizeof *B->timeout)))
    112 	return luaL_error(L, "%s", strerror(errno));
    113 
    114 if (!(B->solib = dlopen(path, RTLD_NOW|RTLD_LOCAL)))
    115 	return luaL_error(L, "%s: %s", path, dlerror());
    116 
    117 if (!(ops = dlsym(B->solib, "benchops")))
    118 	return luaL_error(L, "%s: %s", path, dlerror());
    119 
    120 B->ops = *ops;
    121 B->state = B->ops.init(B->timeout, B->count, B->verbose);
    122 
    123 return 1;
    124 } /* bench_new() */
    125 
    126 
    127 static int bench_add(lua_State *L) {
    128 struct bench *B = lua_touserdata(L, 1);
    129 unsigned i;
    130 timeout_t t;
    131 
    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);
    134 
    135 B->ops.add(B->state, &B->timeout[i], t);
    136 
    137 return 0;
    138 } /* bench_add() */
    139 
    140 
    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);
    145 
    146 while (i <= j && i < B->count) {
    147 	B->ops.del(B->state, &B->timeout[i]);
    148 	++i;
    149 }
    150 
    151 return 0;
    152 } /* bench_del() */
    153 
    154 
    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;
    159 size_t i;
    160 
    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);
    165 		timeout_max = MAX(timeout, timeout_max);
    166 	}
    167 } else {
    168 	for (i = 0; i < count; i++) {
    169 		timeout = timeout_inc + i;
    170 		B->ops.add(B->state, &B->timeout[i], timeout_inc + i);
    171 		timeout_max = MAX(timeout, timeout_max);
    172 	}
    173 }
    174 
    175 lua_pushinteger(L, (lua_Integer)count);
    176 lua_pushinteger(L, (lua_Integer)timeout_max);
    177 
    178 return 2;
    179 } /* bench_fill() */
    180 
    181 
    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);
    186 size_t i = 0;
    187 
    188 while (i < count && !B->ops.empty(B->state)) {
    189 	B->curtime += step;
    190 	B->ops.update(B->state, B->curtime);
    191 
    192 	while (B->ops.get(B->state))
    193 		i++;
    194 }
    195 
    196 lua_pushinteger(L, (lua_Integer)i);
    197 
    198 return 1;
    199 } /* bench_expire() */
    200 
    201 
    202 static int bench_empty(lua_State *L) {
    203 struct bench *B = lua_touserdata(L, 1);
    204 
    205 lua_pushboolean(L, B->ops.empty(B->state));
    206 
    207 return 1;
    208 } /* bench_empty() */
    209 
    210 
    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));
    214 struct timeout *to;
    215 
    216 if (!B->ops.next || !(to = B->ops.next(B->state, it)))
    217 	return 0;
    218 
    219 lua_pushinteger(L, luaL_optinteger(L, 2, 0) + 1);
    220 
    221 lua_newtable(L);
    222 lua_pushinteger(L, to->expires);
    223 lua_setfield(L, -2, "expires");
    224 
    225 return 2;
    226 } /* bench__next() */
    227 
    228 static int bench__pairs(lua_State *L) {
    229 struct timeouts_it *it;
    230 
    231 lua_settop(L, 1);
    232 
    233 it = lua_newuserdata(L, sizeof *it);
    234 TIMEOUTS_IT_INIT(it, TIMEOUTS_ALL);
    235 
    236 lua_pushcclosure(L, &bench__next, 2);
    237 lua_pushvalue(L, 1);
    238 lua_pushinteger(L, 0);
    239 
    240 return 3;
    241 } /* bench__pairs() */
    242 
    243 
    244 static int bench__gc(lua_State *L) {
    245 struct bench *B = lua_touserdata(L, 1);
    246 
    247 if (B->state) {
    248 	B->ops.destroy(B->state);
    249 	B->state = NULL;
    250 }
    251 
    252 return 0;
    253 } /* bench__gc() */
    254 
    255 
    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 },
    263 { NULL,     NULL }
    264 };
    265 
    266 static const luaL_Reg bench_metatable[] = {
    267 { "__pairs", &bench__pairs },
    268 { "__gc",    &bench__gc },
    269 { NULL,      NULL }
    270 };
    271 
    272 static const luaL_Reg bench_globals[] = {
    273 { "new",   &bench_new },
    274 { "clock", &bench_clock },
    275 { NULL,  NULL }
    276 };
    277 
    278 int luaopen_bench(lua_State *L) {
    279 #if __APPLE__
    280 mach_timebase_info(&timebase);
    281 #endif
    282 
    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");
    287 }
    288 
    289 luaL_newlib(L, bench_globals);
    290 
    291 return 1;
    292 } /* luaopen_bench() */