local basics = {} local MIN_FUZZ_SECS = 0.5 local MIN_BENCH_SECS = 0.1 local MIN_WARMUP_SECS = 0.1 local MIN_FUZZ_ITERS = 100 local MIN_BENCH_ITERS = 100 local MIN_WARMUP_ITERS = 100 local __table_pack = (function() ---@diagnostic disable-next-line: deprecated return table.pack or function(...) return { n = select('#', ...), ... } end end)() local __table_unpack = (function() ---@diagnostic disable-next-line: deprecated return table.unpack or unpack end)() ---@param pattern string function basics.unload(pattern) for name, _ in pairs(package.loaded) do if name:match(pattern) then package.loaded[name] = nil end end end ---@param modname string function basics.describe_fuzz(modname) basics.unload('evolved') print(string.format('| %s ... |', modname)) collectgarbage('collect') collectgarbage('stop') do local iters = 0 local start_s = os.clock() local start_kb = collectgarbage('count') local success, result = pcall(function() repeat iters = iters + 1 basics.unload(modname) require(modname) until iters >= MIN_FUZZ_ITERS and os.clock() - start_s >= MIN_FUZZ_SECS end) local finish_s = os.clock() local finish_kb = collectgarbage('count') if success then print(string.format('|-- PASS | us: %.2f | op/s: %.2f | kb/i: %.2f | iters: %d', (finish_s - start_s) * 1e6 / iters, iters / (finish_s - start_s), (finish_kb - start_kb) / iters, iters)) else print('|-- FUZZ FAIL: ' .. result) end end collectgarbage('restart') collectgarbage('collect') end ---@param name string ---@param loop fun(...): ... ---@param init? fun(): ... ---@param fini? fun(...): ... function basics.describe_bench(name, loop, init, fini) basics.unload('evolved') print(string.format('| %s ... |', name)) local state = init and __table_pack(init()) or {} do local iters = 0 local warmup_s = os.clock() local success, result = pcall(function() repeat iters = iters + 1 loop(__table_unpack(state)) until iters >= MIN_WARMUP_ITERS and os.clock() - warmup_s > MIN_WARMUP_SECS end) if not success then print('|-- WARMUP FAIL: ' .. result) return end end collectgarbage('collect') collectgarbage('stop') do local iters = 0 local start_s = os.clock() local start_kb = collectgarbage('count') local success, result = pcall(function() repeat iters = iters + 1 loop(__table_unpack(state)) until iters >= MIN_BENCH_ITERS and os.clock() - start_s > MIN_BENCH_SECS end) local finish_s = os.clock() local finish_kb = collectgarbage('count') if success then print(string.format('|-- PASS | us: %.2f | op/s: %.2f | kb/i: %.2f | iters: %d', (finish_s - start_s) * 1e6 / iters, iters / (finish_s - start_s), (finish_kb - start_kb) / iters, iters)) else print('|-- LOOP FAIL: ' .. result) end end if fini then local success, result = pcall(function() fini(__table_unpack(state)) end) if not success then print('|-- FINI FAIL: ' .. result) end end collectgarbage('restart') collectgarbage('collect') end return basics