CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-hapi--hoek

General purpose node utilities providing object manipulation, array operations, string utilities, data validation, async utilities, and path operations for the hapi ecosystem.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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

docs

array-operations.md

async-promise-utilities.md

data-utilities.md

function-utilities.md

index.md

object-operations.md

path-operations.md

performance-benchmarking.md

string-utilities.md

validation-assertions.md

tile.json