High-resolution benchmarking tools for performance measurement using Node.js hrtime for maximum accuracy in timing operations and performance analysis.
A benchmarking timer class using Node.js internal high-resolution time for accurate performance measurement.
/**
* A benchmarking timer, using the internal node clock for maximum accuracy
*/
class Bench {
constructor();
/** The starting high-resolution timestamp in milliseconds */
ts: number;
/** The time in milliseconds since the object was created */
elapsed(): number;
/** Reset the ts value to now */
reset(): void;
/** The current high-resolution time in milliseconds */
static now(): number;
}Usage Examples:
import { Bench } from "@hapi/hoek";
// Basic benchmarking
const bench = new Bench();
// Simulate some work
for (let i = 0; i < 1000000; i++) {
Math.sqrt(i);
}
console.log(`Operation took ${bench.elapsed()}ms`);
// Multiple measurements with reset
const timer = new Bench();
// First operation
performOperation1();
const time1 = timer.elapsed();
console.log(`Operation 1: ${time1}ms`);
timer.reset(); // Reset for next measurement
// Second operation
performOperation2();
const time2 = timer.elapsed();
console.log(`Operation 2: ${time2}ms`);
// Comparing different approaches
function benchmarkApproaches() {
const results: Record<string, number> = {};
// Approach 1
const bench1 = new Bench();
approach1();
results.approach1 = bench1.elapsed();
// Approach 2
const bench2 = new Bench();
approach2();
results.approach2 = bench2.elapsed();
// Approach 3
const bench3 = new Bench();
approach3();
results.approach3 = bench3.elapsed();
return results;
}
// Async operation benchmarking
async function benchmarkAsync() {
const bench = new Bench();
await asyncOperation();
console.log(`Async operation took ${bench.elapsed()}ms`);
}
// High-precision timing
function precisionTiming() {
const start = Bench.now();
// Very fast operation
const result = 2 + 2;
const end = Bench.now();
console.log(`Microsecond precision: ${end - start}ms`);
}
// Performance profiling class
class PerformanceProfiler {
private timers: Map<string, Bench> = new Map();
private results: Map<string, number[]> = new Map();
start(label: string): void {
this.timers.set(label, new Bench());
}
end(label: string): number {
const timer = this.timers.get(label);
if (!timer) {
throw new Error(`Timer '${label}' not found`);
}
const elapsed = timer.elapsed();
if (!this.results.has(label)) {
this.results.set(label, []);
}
this.results.get(label)!.push(elapsed);
this.timers.delete(label);
return elapsed;
}
getStats(label: string) {
const times = this.results.get(label) || [];
if (times.length === 0) return null;
const sum = times.reduce((a, b) => a + b, 0);
const avg = sum / times.length;
const min = Math.min(...times);
const max = Math.max(...times);
return { avg, min, max, count: times.length, total: sum };
}
}
// Usage of profiler
const profiler = new PerformanceProfiler();
for (let i = 0; i < 100; i++) {
profiler.start('operation');
performSomeOperation();
profiler.end('operation');
}
console.log(profiler.getStats('operation'));
// API response timing
async function timeAPICall(url: string) {
const bench = new Bench();
try {
const response = await fetch(url);
const data = await response.json();
const totalTime = bench.elapsed();
console.log(`API call to ${url} took ${totalTime}ms`);
return { data, timing: totalTime };
} catch (error) {
const failTime = bench.elapsed();
console.log(`API call failed after ${failTime}ms`);
throw error;
}
}
// Database query benchmarking
class DatabaseBenchmark {
async benchmarkQuery(query: string, iterations = 10) {
const times: number[] = [];
for (let i = 0; i < iterations; i++) {
const bench = new Bench();
await executeQuery(query);
times.push(bench.elapsed());
}
return {
query,
iterations,
avgTime: times.reduce((a, b) => a + b, 0) / times.length,
minTime: Math.min(...times),
maxTime: Math.max(...times),
times
};
}
}
// Memory and timing combined
function comprehensiveBenchmark(operation: Function) {
const initialMemory = process.memoryUsage();
const bench = new Bench();
const result = operation();
const elapsed = bench.elapsed();
const finalMemory = process.memoryUsage();
return {
result,
timing: elapsed,
memoryDelta: {
heapUsed: finalMemory.heapUsed - initialMemory.heapUsed,
heapTotal: finalMemory.heapTotal - initialMemory.heapTotal,
rss: finalMemory.rss - initialMemory.rss
}
};
}
// Load testing helper
async function loadTest(operation: () => Promise<any>, concurrency = 10, iterations = 100) {
const results: number[] = [];
const overallBench = new Bench();
for (let batch = 0; batch < iterations; batch += concurrency) {
const batchPromises = [];
for (let i = 0; i < concurrency && batch + i < iterations; i++) {
const bench = new Bench();
batchPromises.push(
operation().then(() => bench.elapsed())
);
}
const batchResults = await Promise.all(batchPromises);
results.push(...batchResults);
}
const totalTime = overallBench.elapsed();
return {
totalIterations: iterations,
totalTime,
avgTime: results.reduce((a, b) => a + b, 0) / results.length,
minTime: Math.min(...results),
maxTime: Math.max(...results),
throughput: iterations / (totalTime / 1000) // operations per second
};
}
// Real-world usage example
async function benchmarkDataProcessing() {
const data = generateLargeDataset();
console.log('Benchmarking data processing approaches...');
// Sequential processing
const seqBench = new Bench();
const seqResult = await processSequentially(data);
const seqTime = seqBench.elapsed();
// Parallel processing
const parBench = new Bench();
const parResult = await processInParallel(data);
const parTime = parBench.elapsed();
// Chunked processing
const chunkBench = new Bench();
const chunkResult = await processInChunks(data);
const chunkTime = chunkBench.elapsed();
console.log({
sequential: `${seqTime}ms`,
parallel: `${parTime}ms`,
chunked: `${chunkTime}ms`,
winner: seqTime < parTime && seqTime < chunkTime ? 'sequential' :
parTime < chunkTime ? 'parallel' : 'chunked'
});
}Important Notes:
Bench uses Node.js process.hrtime() for sub-millisecond precision timingts property stores high-resolution time, not standard Date timestampsDate.now() for performance measurement due to higher resolutionelapsed() method returns time in milliseconds with decimal precisionBench.now() is a static method providing current high-resolution time