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