@@ -1868,6 +1868,45 @@ added:
18681868
18691869The number of samples recorded by the histogram.
18701870
1871+ ### ` histogram.ccdf(value) `
1872+
1873+ <!-- YAML
1874+ added: REPLACEME
1875+ -->
1876+
1877+ * ` value ` {number} The value to query.
1878+ * Returns: {number} A probability between 0.0 and 1.0.
1879+
1880+ Returns the complementary cumulative distribution function (CCDF) value
1881+ for the given value, representing the probability that a recorded value
1882+ will exceed ` value ` . Equivalent to ` 1 - histogram.cdf(value) ` .
1883+
1884+ ### ` histogram.cdf(value) `
1885+
1886+ <!-- YAML
1887+ added: REPLACEME
1888+ -->
1889+
1890+ * ` value ` {number} The value to query.
1891+ * Returns: {number} A probability between 0.0 and 1.0.
1892+
1893+ Returns the cumulative distribution function (CDF) value for the given
1894+ value, representing the probability that a recorded value will be less
1895+ than or equal to ` value ` . This is the inverse operation of
1896+ ` histogram.percentile() ` .
1897+
1898+ ### ` histogram.countAt(value) `
1899+
1900+ <!-- YAML
1901+ added: REPLACEME
1902+ -->
1903+
1904+ * ` value ` {number} The value to query.
1905+ * Returns: {number}
1906+
1907+ Returns the number of recorded values that fall within the equivalent
1908+ value range of the given value.
1909+
18711910### ` histogram.exceeds `
18721911
18731912<!-- YAML
@@ -1892,6 +1931,59 @@ added:
18921931The number of times the event loop delay exceeded the maximum 1 hour event
18931932loop delay threshold.
18941933
1934+ ### ` histogram.ksTest(other) `
1935+
1936+ <!-- YAML
1937+ added: REPLACEME
1938+ -->
1939+
1940+ * ` other ` {Histogram} The histogram to compare against.
1941+ * Returns: {number} The KS D-statistic, between 0.0 and 1.0.
1942+
1943+ Computes the Kolmogorov-Smirnov test statistic comparing this histogram's
1944+ distribution to ` other ` . A value of 0 indicates identical distributions;
1945+ values close to 1 indicate completely disjoint distributions. Useful for
1946+ detecting performance regressions by comparing before/after histograms.
1947+
1948+ ### ` histogram.kurtosis `
1949+
1950+ <!-- YAML
1951+ added: REPLACEME
1952+ -->
1953+
1954+ * Type: {number}
1955+
1956+ The excess kurtosis of the recorded values. Measures the heaviness of the
1957+ distribution's tails relative to a normal distribution. Positive values
1958+ indicate heavier tails (more extreme outliers); negative values indicate
1959+ lighter tails.
1960+
1961+ ### ` histogram.linearBuckets(stepSize) `
1962+
1963+ <!-- YAML
1964+ added: REPLACEME
1965+ -->
1966+
1967+ * ` stepSize ` {number} The width of each linear bucket.
1968+ * Returns: {Map} A map of bucket boundary values to counts.
1969+
1970+ Returns the histogram data rebucketed into linearly-spaced intervals
1971+ of ` stepSize ` . Useful for visualization and export.
1972+
1973+ ### ` histogram.logBuckets(firstBucket, base) `
1974+
1975+ <!-- YAML
1976+ added: REPLACEME
1977+ -->
1978+
1979+ * ` firstBucket ` {number} The value of the first bucket boundary.
1980+ * ` base ` {number} The logarithmic base for bucket width growth. Must be > 1.
1981+ * Returns: {Map} A map of bucket boundary values to counts.
1982+
1983+ Returns the histogram data rebucketed into logarithmically-spaced
1984+ intervals, where each bucket's width is multiplied by ` base ` .
1985+ Useful for visualization and export.
1986+
18951987### ` histogram.max `
18961988
18971989<!-- YAML
@@ -1992,6 +2084,20 @@ added:
19922084
19932085Returns a ` Map ` object detailing the accumulated percentile distribution.
19942086
2087+ ### ` histogram.percentilesAt(percentiles) `
2088+
2089+ <!-- YAML
2090+ added: REPLACEME
2091+ -->
2092+
2093+ * ` percentiles ` {number\[ ] } An array of percentile values in the range (0, 100] .
2094+ * Returns: {Map} A map of percentile values to their corresponding histogram
2095+ values.
2096+
2097+ Returns the values at the specified percentiles, computed in a single
2098+ efficient pass over the histogram data. More efficient than calling
2099+ ` histogram.percentile() ` multiple times.
2100+
19952101### ` histogram.reset() `
19962102
19972103<!-- YAML
@@ -2000,6 +2106,19 @@ added: v11.10.0
20002106
20012107Resets the collected histogram data.
20022108
2109+ ### ` histogram.skewness `
2110+
2111+ <!-- YAML
2112+ added: REPLACEME
2113+ -->
2114+
2115+ * Type: {number}
2116+
2117+ The skewness of the recorded values. Measures the asymmetry of the
2118+ distribution. A positive value indicates a right-skewed distribution
2119+ (longer right tail, common for latency data); a negative value
2120+ indicates a left-skewed distribution.
2121+
20032122### ` histogram.stddev `
20042123
20052124<!-- YAML
@@ -2101,6 +2220,127 @@ added:
21012220Calculates the amount of time (in nanoseconds) that has passed since the
21022221previous call to ` recordDelta() ` and records that amount in the histogram.
21032222
2223+ ### ` histogram.recordCorrected(val, expectedInterval) `
2224+
2225+ <!-- YAML
2226+ added: REPLACEME
2227+ -->
2228+
2229+ * ` val ` {number|bigint} The value to record.
2230+ * ` expectedInterval ` {number|bigint} The expected recording interval.
2231+
2232+ Records a value with coordinated omission correction. When a system stall
2233+ prevents timely recording, this method backfills intermediate values at
2234+ ` expectedInterval ` steps between the previously recorded value and ` val ` .
2235+ This compensates for measurement gaps that would otherwise underrepresent
2236+ latency.
2237+
2238+ ### ` histogram.subtract(other) `
2239+
2240+ <!-- YAML
2241+ added: REPLACEME
2242+ -->
2243+
2244+ * ` other ` {RecordableHistogram}
2245+
2246+ Subtracts the values of ` other ` from this histogram. Both histograms should
2247+ have compatible configurations. Bucket counts that would become negative
2248+ are clamped to zero.
2249+
2250+ ## Histogram analysis examples
2251+
2252+ The ` Histogram ` class provides statistical analysis methods useful for
2253+ performance monitoring, SLO enforcement, and regression detection.
2254+
2255+ ### Distribution shape analysis
2256+
2257+ ``` js
2258+ const { createHistogram } = require (' node:perf_hooks' );
2259+
2260+ const h = createHistogram ();
2261+
2262+ // Simulate a right-skewed latency distribution
2263+ for (let i = 0 ; i < 1000 ; i++ ) {
2264+ h .record (Math .ceil (Math .random () * 100 ));
2265+ }
2266+ // Add some outliers
2267+ for (let i = 0 ; i < 10 ; i++ ) {
2268+ h .record (500 + Math .ceil (Math .random () * 500 ));
2269+ }
2270+
2271+ console .log (' Skewness:' , h .skewness .toFixed (4 )); // Positive = right-skewed
2272+ console .log (' Kurtosis:' , h .kurtosis .toFixed (4 )); // Positive = heavy tails
2273+ ```
2274+
2275+ ### SLO monitoring with CDF
2276+
2277+ ``` js
2278+ const { createHistogram } = require (' node:perf_hooks' );
2279+
2280+ const latency = createHistogram ();
2281+
2282+ // Record request latencies (in nanoseconds)...
2283+
2284+ // "What fraction of requests complete within 100ms?"
2285+ const withinSLO = latency .cdf (100_000_000 );
2286+ console .log (` ${ (withinSLO * 100 ).toFixed (1 )} % of requests within SLO` );
2287+
2288+ // "What fraction of requests exceed 500ms?"
2289+ const violating = latency .ccdf (500_000_000 );
2290+ console .log (` ${ (violating * 100 ).toFixed (1 )} % of requests violating SLO` );
2291+ ```
2292+
2293+ ### Regression detection with KS test
2294+
2295+ ``` js
2296+ const { createHistogram } = require (' node:perf_hooks' );
2297+
2298+ const baseline = createHistogram ();
2299+ const current = createHistogram ();
2300+
2301+ // Record baseline and current latencies...
2302+
2303+ // D-statistic: 0 = identical, 1 = completely different
2304+ const d = baseline .ksTest (current);
2305+ if (d > 0.1 ) {
2306+ console .log (` Possible regression detected (D=${ d .toFixed (4 )} )` );
2307+ }
2308+ ```
2309+
2310+ ### Batch percentile queries
2311+
2312+ ``` js
2313+ const { createHistogram } = require (' node:perf_hooks' );
2314+
2315+ const h = createHistogram ();
2316+ // Record values...
2317+
2318+ // Efficiently query common monitoring percentiles in one pass
2319+ const p = h .percentilesAt ([50 , 75 , 90 , 95 , 99 , 99.9 ]);
2320+ console .log (' p50:' , p .get (50 ));
2321+ console .log (' p99:' , p .get (99 ));
2322+ ```
2323+
2324+ ### Snapshot diffing with subtract
2325+
2326+ ``` js
2327+ const { createHistogram } = require (' node:perf_hooks' );
2328+
2329+ const total = createHistogram ();
2330+ const snapshot = createHistogram ();
2331+
2332+ // Record values into total...
2333+ // Periodically snapshot for "last interval" analysis:
2334+ snapshot .add (total);
2335+
2336+ // Later, take a new snapshot and diff:
2337+ const newSnapshot = createHistogram ();
2338+ newSnapshot .add (total);
2339+ newSnapshot .subtract (snapshot);
2340+ // newSnapshot now contains only the values recorded since the last snapshot
2341+ console .log (' Recent p99:' , newSnapshot .percentile (99 ));
2342+ ```
2343+
21042344## Examples
21052345
21062346### Measuring the duration of async operations
0 commit comments