HdrHistogram.js
HdrHistogram.js is a TypeScript port of the HdrHistogram library, designed for high-fidelity recording and analysis of latency and other value distributions in both Node.js and web browser environments. The library is currently stable at version 3.0.1, with a history of regular updates including significant architectural changes. A key differentiator since version 2 is the introduction of an optional WebAssembly (WASM) implementation, leveraging AssemblyScript to provide substantial performance gains for recording and processing histograms, though this is not enabled by default. It supports core HdrHistogram features such as regular and coordinated omission-corrected latency recording, resizable and memory-optimized 'packed' histograms, and the ability to add, subtract, encode, and decode compressed histograms. It also includes client-side data visualization tools for browser-based analysis. Release cadence appears to be driven by feature enhancements and performance optimizations, with major versions often introducing substantial improvements.
Common errors
-
ReferenceError: require is not defined
cause Attempting to use CommonJS `require()` syntax in an ES Module context (e.g., a file with `"type": "module"` in `package.json` or `.mjs` extension).fixConvert `require('hdr-histogram-js')` to `import * as hdr from 'hdr-histogram-js'` or `import { build } from 'hdr-histogram-js'`. -
TypeError: build is not a function
cause Attempting to import the `build` function as a default import (e.g., `import build from 'hdr-histogram-js'`) when it is a named export.fixUse named import syntax: `import { build } from 'hdr-histogram-js'`. -
WebAssembly is not available in this environment
cause The `useWebAssembly: true` option was provided when building a histogram, but the current runtime environment (e.g., an older browser, specific Node.js configuration) does not support WebAssembly or has it disabled.fixEither remove `useWebAssembly: true` to fall back to the TypeScript implementation, or ensure the execution environment fully supports WebAssembly (e.g., update browser, use a compatible Node.js version).
Warnings
- breaking Version 2.0.0 introduced significant architectural changes and the optional WebAssembly (WASM) implementation. While not strictly 'breaking' for API compatibility, performance characteristics and default behaviors changed.
- gotcha The WebAssembly implementation, introduced in v2.0.0, offers significant performance benefits but is not enabled by default. Users must explicitly opt-in if they wish to use it.
- gotcha Choosing the correct `bitBucketSize` or using the `'packed'` option influences both memory footprint and performance. 'packed' histograms use less memory but are significantly slower.
- gotcha The library explicitly lists a Node.js engine requirement of `>=14`.
Install
-
npm install hdr-histogram-js -
yarn add hdr-histogram-js -
pnpm add hdr-histogram-js
Imports
- hdr
import hdr from 'hdr-histogram-js'
import * as hdr from 'hdr-histogram-js'
- build
import build from 'hdr-histogram-js'
import { build } from 'hdr-histogram-js' - Histogram
import Histogram from 'hdr-histogram-js'
import { Histogram } from 'hdr-histogram-js' - CommonJS require
const hdr = require('hdr-histogram-js').defaultconst hdr = require('hdr-histogram-js')
Quickstart
import { build, Histogram } from 'hdr-histogram-js';
// Build a default histogram with auto-resizing, tracking values from 1 to 2, and 3 significant digits.
// WebAssembly is not enabled by default for maximum compatibility.
const histogram: Histogram = build({
lowestDiscernibleValue: 1,
highestTrackableValue: 10000000000, // 10 billion
numberOfSignificantValueDigits: 3,
useWebAssembly: false // Explicitly set to false, true for performance if available
});
// Record some values representing latencies in microseconds
histogram.recordValue(1000);
histogram.recordValue(5000);
histogram.recordValue(100);
for (let i = 0; i < 1000; i++) {
histogram.recordValue(Math.floor(Math.random() * 9000) + 1000);
}
histogram.recordValue(9999);
console.log(`Total count: ${histogram.totalCount}`);
console.log(`90th percentile: ${histogram.getValueAtPercentile(90)} µs`);
console.log(`99th percentile: ${histogram.getValueAtPercentile(99)} µs`);
console.log(`Max value: ${histogram.maxValue} µs`);
// Example of coordinated omission correction
const histogramWithCoordinatedOmissions = build({
lowestDiscernibleValue: 1,
highestTrackableValue: 10000000000,
numberOfSignificantValueDigits: 3
});
histogramWithCoordinatedOmissions.recordValueWithExpectedInterval(100, 10); // Record a value of 100, expecting 10ms interval
console.log(`
Histogram with coordinated omissions (total count: ${histogramWithCoordinatedOmissions.totalCount}):`);
console.log(`90th percentile (corrected): ${histogramWithCoordinatedOmissions.getValueAtPercentile(90)} µs`);