or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

array-operations.mdasync-promise-utilities.mddata-utilities.mdfunction-utilities.mdindex.mdobject-operations.mdpath-operations.mdperformance-benchmarking.mdstring-utilities.mdvalidation-assertions.md
tile.json

performance-benchmarking.mddocs/

Performance and Benchmarking

High-resolution benchmarking tools for performance measurement using Node.js hrtime for maximum accuracy in timing operations and performance analysis.

Capabilities

Bench Class

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 timing
  • The ts property stores high-resolution time, not standard Date timestamps
  • More accurate than Date.now() for performance measurement due to higher resolution
  • elapsed() method returns time in milliseconds with decimal precision
  • Bench.now() is a static method providing current high-resolution time
  • Perfect for micro-benchmarks, API timing, and performance profiling
  • Reset functionality allows reusing the same timer instance for multiple measurements
  • Works well with both synchronous and asynchronous operations