@@ -1858,6 +1858,45 @@ added:
18581858
18591859The number of samples recorded by the histogram.
18601860
1861+ ### ` histogram.ccdf(value) `
1862+
1863+ <!-- YAML
1864+ added: REPLACEME
1865+ -->
1866+
1867+ * ` value ` {number} The value to query.
1868+ * Returns: {number} A probability between 0.0 and 1.0.
1869+
1870+ Returns the complementary cumulative distribution function (CCDF) value
1871+ for the given value, representing the probability that a recorded value
1872+ will exceed ` value ` . Equivalent to ` 1 - histogram.cdf(value) ` .
1873+
1874+ ### ` histogram.cdf(value) `
1875+
1876+ <!-- YAML
1877+ added: REPLACEME
1878+ -->
1879+
1880+ * ` value ` {number} The value to query.
1881+ * Returns: {number} A probability between 0.0 and 1.0.
1882+
1883+ Returns the cumulative distribution function (CDF) value for the given
1884+ value, representing the probability that a recorded value will be less
1885+ than or equal to ` value ` . This is the inverse operation of
1886+ ` histogram.percentile() ` .
1887+
1888+ ### ` histogram.countAt(value) `
1889+
1890+ <!-- YAML
1891+ added: REPLACEME
1892+ -->
1893+
1894+ * ` value ` {number} The value to query.
1895+ * Returns: {number}
1896+
1897+ Returns the number of recorded values that fall within the equivalent
1898+ value range of the given value.
1899+
18611900### ` histogram.exceeds `
18621901
18631902<!-- YAML
@@ -1882,6 +1921,59 @@ added:
18821921The number of times the event loop delay exceeded the maximum 1 hour event
18831922loop delay threshold.
18841923
1924+ ### ` histogram.ksTest(other) `
1925+
1926+ <!-- YAML
1927+ added: REPLACEME
1928+ -->
1929+
1930+ * ` other ` {Histogram} The histogram to compare against.
1931+ * Returns: {number} The KS D-statistic, between 0.0 and 1.0.
1932+
1933+ Computes the Kolmogorov-Smirnov test statistic comparing this histogram's
1934+ distribution to ` other ` . A value of 0 indicates identical distributions;
1935+ values close to 1 indicate completely disjoint distributions. Useful for
1936+ detecting performance regressions by comparing before/after histograms.
1937+
1938+ ### ` histogram.kurtosis `
1939+
1940+ <!-- YAML
1941+ added: REPLACEME
1942+ -->
1943+
1944+ * Type: {number}
1945+
1946+ The excess kurtosis of the recorded values. Measures the heaviness of the
1947+ distribution's tails relative to a normal distribution. Positive values
1948+ indicate heavier tails (more extreme outliers); negative values indicate
1949+ lighter tails.
1950+
1951+ ### ` histogram.linearBuckets(stepSize) `
1952+
1953+ <!-- YAML
1954+ added: REPLACEME
1955+ -->
1956+
1957+ * ` stepSize ` {number} The width of each linear bucket.
1958+ * Returns: {Map} A map of bucket boundary values to counts.
1959+
1960+ Returns the histogram data rebucketed into linearly-spaced intervals
1961+ of ` stepSize ` . Useful for visualization and export.
1962+
1963+ ### ` histogram.logBuckets(firstBucket, base) `
1964+
1965+ <!-- YAML
1966+ added: REPLACEME
1967+ -->
1968+
1969+ * ` firstBucket ` {number} The value of the first bucket boundary.
1970+ * ` base ` {number} The logarithmic base for bucket width growth. Must be > 1.
1971+ * Returns: {Map} A map of bucket boundary values to counts.
1972+
1973+ Returns the histogram data rebucketed into logarithmically-spaced
1974+ intervals, where each bucket's width is multiplied by ` base ` .
1975+ Useful for visualization and export.
1976+
18851977### ` histogram.max `
18861978
18871979<!-- YAML
@@ -1982,6 +2074,20 @@ added:
19822074
19832075Returns a ` Map ` object detailing the accumulated percentile distribution.
19842076
2077+ ### ` histogram.percentilesAt(percentiles) `
2078+
2079+ <!-- YAML
2080+ added: REPLACEME
2081+ -->
2082+
2083+ * ` percentiles ` {number\[ ] } An array of percentile values in the range (0, 100] .
2084+ * Returns: {Map} A map of percentile values to their corresponding histogram
2085+ values.
2086+
2087+ Returns the values at the specified percentiles, computed in a single
2088+ efficient pass over the histogram data. More efficient than calling
2089+ ` histogram.percentile() ` multiple times.
2090+
19852091### ` histogram.reset() `
19862092
19872093<!-- YAML
@@ -1990,6 +2096,19 @@ added: v11.10.0
19902096
19912097Resets the collected histogram data.
19922098
2099+ ### ` histogram.skewness `
2100+
2101+ <!-- YAML
2102+ added: REPLACEME
2103+ -->
2104+
2105+ * Type: {number}
2106+
2107+ The skewness of the recorded values. Measures the asymmetry of the
2108+ distribution. A positive value indicates a right-skewed distribution
2109+ (longer right tail, common for latency data); a negative value
2110+ indicates a left-skewed distribution.
2111+
19932112### ` histogram.stddev `
19942113
19952114<!-- YAML
@@ -2091,6 +2210,127 @@ added:
20912210Calculates the amount of time (in nanoseconds) that has passed since the
20922211previous call to ` recordDelta() ` and records that amount in the histogram.
20932212
2213+ ### ` histogram.recordCorrected(val, expectedInterval) `
2214+
2215+ <!-- YAML
2216+ added: REPLACEME
2217+ -->
2218+
2219+ * ` val ` {number|bigint} The value to record.
2220+ * ` expectedInterval ` {number|bigint} The expected recording interval.
2221+
2222+ Records a value with coordinated omission correction. When a system stall
2223+ prevents timely recording, this method backfills intermediate values at
2224+ ` expectedInterval ` steps between the previously recorded value and ` val ` .
2225+ This compensates for measurement gaps that would otherwise underrepresent
2226+ latency.
2227+
2228+ ### ` histogram.subtract(other) `
2229+
2230+ <!-- YAML
2231+ added: REPLACEME
2232+ -->
2233+
2234+ * ` other ` {RecordableHistogram}
2235+
2236+ Subtracts the values of ` other ` from this histogram. Both histograms should
2237+ have compatible configurations. Bucket counts that would become negative
2238+ are clamped to zero.
2239+
2240+ ## Histogram analysis examples
2241+
2242+ The ` Histogram ` class provides statistical analysis methods useful for
2243+ performance monitoring, SLO enforcement, and regression detection.
2244+
2245+ ### Distribution shape analysis
2246+
2247+ ``` js
2248+ const { createHistogram } = require (' node:perf_hooks' );
2249+
2250+ const h = createHistogram ();
2251+
2252+ // Simulate a right-skewed latency distribution
2253+ for (let i = 0 ; i < 1000 ; i++ ) {
2254+ h .record (Math .ceil (Math .random () * 100 ));
2255+ }
2256+ // Add some outliers
2257+ for (let i = 0 ; i < 10 ; i++ ) {
2258+ h .record (500 + Math .ceil (Math .random () * 500 ));
2259+ }
2260+
2261+ console .log (' Skewness:' , h .skewness .toFixed (4 )); // Positive = right-skewed
2262+ console .log (' Kurtosis:' , h .kurtosis .toFixed (4 )); // Positive = heavy tails
2263+ ```
2264+
2265+ ### SLO monitoring with CDF
2266+
2267+ ``` js
2268+ const { createHistogram } = require (' node:perf_hooks' );
2269+
2270+ const latency = createHistogram ();
2271+
2272+ // Record request latencies (in nanoseconds)...
2273+
2274+ // "What fraction of requests complete within 100ms?"
2275+ const withinSLO = latency .cdf (100_000_000 );
2276+ console .log (` ${ (withinSLO * 100 ).toFixed (1 )} % of requests within SLO` );
2277+
2278+ // "What fraction of requests exceed 500ms?"
2279+ const violating = latency .ccdf (500_000_000 );
2280+ console .log (` ${ (violating * 100 ).toFixed (1 )} % of requests violating SLO` );
2281+ ```
2282+
2283+ ### Regression detection with KS test
2284+
2285+ ``` js
2286+ const { createHistogram } = require (' node:perf_hooks' );
2287+
2288+ const baseline = createHistogram ();
2289+ const current = createHistogram ();
2290+
2291+ // Record baseline and current latencies...
2292+
2293+ // D-statistic: 0 = identical, 1 = completely different
2294+ const d = baseline .ksTest (current);
2295+ if (d > 0.1 ) {
2296+ console .log (` Possible regression detected (D=${ d .toFixed (4 )} )` );
2297+ }
2298+ ```
2299+
2300+ ### Batch percentile queries
2301+
2302+ ``` js
2303+ const { createHistogram } = require (' node:perf_hooks' );
2304+
2305+ const h = createHistogram ();
2306+ // Record values...
2307+
2308+ // Efficiently query common monitoring percentiles in one pass
2309+ const p = h .percentilesAt ([50 , 75 , 90 , 95 , 99 , 99.9 ]);
2310+ console .log (' p50:' , p .get (50 ));
2311+ console .log (' p99:' , p .get (99 ));
2312+ ```
2313+
2314+ ### Snapshot diffing with subtract
2315+
2316+ ``` js
2317+ const { createHistogram } = require (' node:perf_hooks' );
2318+
2319+ const total = createHistogram ();
2320+ const snapshot = createHistogram ();
2321+
2322+ // Record values into total...
2323+ // Periodically snapshot for "last interval" analysis:
2324+ snapshot .add (total);
2325+
2326+ // Later, take a new snapshot and diff:
2327+ const newSnapshot = createHistogram ();
2328+ newSnapshot .add (total);
2329+ newSnapshot .subtract (snapshot);
2330+ // newSnapshot now contains only the values recorded since the last snapshot
2331+ console .log (' Recent p99:' , newSnapshot .percentile (99 ));
2332+ ```
2333+
20942334## Examples
20952335
20962336### Measuring the duration of async operations
0 commit comments