82 lines
No EOL
2.4 KiB
TypeScript
82 lines
No EOL
2.4 KiB
TypeScript
/**
|
|
* Benchmark — lightweight performance profiling.
|
|
*
|
|
* Usage:
|
|
* import { Benchmark } from "@systems/benchmark";
|
|
*
|
|
* const bench = Benchmark.start("vote");
|
|
* // ... do work ...
|
|
* bench.mark("resolveUser"); // logs: [vote] resolveUser: 12ms
|
|
* // ... more work ...
|
|
* bench.mark("updatePoll"); // logs: [vote] updatePoll: 145ms
|
|
* bench.end(); // logs: [vote] total: 157ms
|
|
*
|
|
* // One-liner:
|
|
* const result = await Benchmark.measure("vote", async () => {
|
|
* return await doSomething();
|
|
* });
|
|
*/
|
|
|
|
import { Logger, logLevel } from "@systems/logger";
|
|
|
|
const log = Logger.for("benchmark");
|
|
|
|
// ─── Active benchmark instance ────────────────────────────────────────────────
|
|
|
|
export interface BenchmarkInstance {
|
|
/** Log time since last mark (or start). */
|
|
mark(label: string): void;
|
|
/** Log total time since start. */
|
|
end(): number;
|
|
}
|
|
|
|
function createBenchmark(name: string, enabled: boolean): BenchmarkInstance {
|
|
let last = Date.now();
|
|
const t0 = last;
|
|
|
|
return {
|
|
mark(label: string): void {
|
|
if (!enabled) return;
|
|
const now = Date.now();
|
|
const delta = now - last;
|
|
last = now;
|
|
log.debug(`[${name}] ${label}: ${delta}ms`);
|
|
},
|
|
|
|
end(): number {
|
|
const total = Date.now() - t0;
|
|
if (enabled) log.debug(`[${name}] total: ${total}ms`);
|
|
return total;
|
|
},
|
|
};
|
|
}
|
|
|
|
// ─── Namespace ────────────────────────────────────────────────────────────────
|
|
|
|
// Only profile when LOG_LEVEL=debug
|
|
const _enabled = () => logLevel() === "DEBUG";
|
|
|
|
export const Benchmark = {
|
|
/**
|
|
* Start a named benchmark.
|
|
* Only active when LOG_LEVEL=debug — zero overhead in production.
|
|
*/
|
|
start(name: string): BenchmarkInstance {
|
|
return createBenchmark(name, _enabled());
|
|
},
|
|
|
|
/**
|
|
* Measure and return the result of an async function.
|
|
*/
|
|
async measure<T>(name: string, fn: () => Promise<T>): Promise<T> {
|
|
const bench = Benchmark.start(name);
|
|
try {
|
|
const result = await fn();
|
|
bench.end();
|
|
return result;
|
|
} catch (err) {
|
|
bench.end();
|
|
throw err;
|
|
}
|
|
},
|
|
}; |