Files
push-take-until/bench/benchlib.js
T

100 lines
2.9 KiB
JavaScript
Raw Normal View History

2026-07-19 13:44:10 -07:00
import fs from 'fs';
const results = [];
async function bench(name, fn, options = {}) {
const iterations = options.iterations || 1;
const warmup = options.warmup || 0;
const unit = options.unit || 'ops/s';
const itemsPerIter = options.itemsPerIter || null;
for (let i = 0; i < warmup; i++) {
await fn();
}
let totalTime = 0;
for (let i = 0; i < iterations; i++) {
const start = process.hrtime.bigint();
await fn();
const end = process.hrtime.bigint();
totalTime += Number(end - start) / 1e6;
}
const avgTime = totalTime / iterations;
const iterPerSec = 1000 / avgTime;
const itemsPerSec = itemsPerIter ? Math.round(iterPerSec * itemsPerIter) : null;
const resultEntry = {
name,
avgTimeMs: parseFloat(avgTime.toFixed(3)),
iterPerSec: Math.round(iterPerSec),
itemsPerSec,
unit,
itemsPerIter,
samples: iterations,
timestamp: new Date().toISOString()
};
results.push(resultEntry);
return resultEntry;
}
async function run(options = {}) {
const outputFile = options.output || './benchmark-results.json';
const threshold = options.regressionThreshold || 0.9;
const output = {
timestamp: new Date().toISOString(),
package: process.env.npm_package_name || 'unknown',
version: process.env.npm_package_version || '0.0.0',
node: process.version,
benchmarks: results
};
if (fs.existsSync(outputFile)) {
const previous = JSON.parse(fs.readFileSync(outputFile, 'utf8'));
if (previous.benchmarks) {
for (const newBench of results) {
const prev = previous.benchmarks.find(b => b.name === newBench.name);
if (prev) {
const ratio = newBench.iterPerSec / prev.iterPerSec;
newBench.regression = ratio < threshold;
newBench.comparedToPrevious = {
iterPerSec: prev.iterPerSec,
ratio: parseFloat(ratio.toFixed(4))
};
}
}
}
}
const regression = results.some(b => b.regression);
console.log('\nBenchmark Results:');
console.log('-'.repeat(90));
console.log(`${'Benchmark'.padEnd(50)} ${'Iter/s'.padStart(10)} ${'Items/s'.padStart(12)} Unit`);
console.log('-'.repeat(90));
for (const r of results) {
const reg = r.regression ? ' [REGRESSION]' : '';
const prev = r.comparedToPrevious ? ` (prev: ${r.comparedToPrevious.iterPerSec}, ratio: ${r.comparedToPrevious.ratio})` : '';
const itemsRate = r.itemsPerSec ? r.itemsPerSec.toString().padStart(12) : ' -';
console.log(`${r.name.padEnd(50)} ${r.iterPerSec.toString().padStart(10)} ${itemsRate} ${r.unit}${reg}${prev}`);
}
console.log('-'.repeat(90));
if (outputFile) {
fs.writeFileSync(outputFile, JSON.stringify(output, null, 2));
console.log(`\nResults saved to: ${outputFile}`);
}
if (regression) {
console.error('\nWARNING: Performance regression detected!');
process.exit(1);
}
return results;
}
export { bench, run };