UNPKG

native-hdr-histogram

Version:

node.js bindings for hdr histogram C implementation

374 lines (266 loc) 12.2 kB
# native-hdr-histogram node.js bindings for [hdr histogram][hdr] [C implementation][cimpl] (version 0.11.1) ![Test](https://github.com/mcollina/native-hdr-histogram/workflows/Test/badge.svg) ![Prebuild Binaries](https://github.com/mcollina/native-hdr-histogram/workflows/Prebuild%20Binaries/badge.svg) [![N-API v3 Badge](https://img.shields.io/badge/N--API-v3-green.svg)](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api) > HDR Histogram is designed for recoding histograms of value measurements in latency and performance sensitive applications. Measurements show value recording times as low as 3-6 nanoseconds on modern (circa 2014) Intel CPUs. A Histogram's memory footprint is constant, with no allocation operations involved in recording data values or in iterating through them. - from [hdr histogram][hdr] website This library is blazingly fast, and you can use it to record histograms with no overhead. Linux, Mac OS X and Windows are all supported. * <a href="#install">Installation</a> * <a href="#example">Example</a> * <a href="#api">API</a> * <a href="#licence">Licence &amp; copyright</a> ## Install ```bash npm i native-hdr-histogram --save ``` If you see any errors, you might need to configure your system to compile native addons: follow the instructions at [node-gyp][node-gyp]. ## Example ```js 'use strict' const Histogram = require('native-hdr-histogram') const max = 1000000 const key = 'record*' + max const histogram = new Histogram(1, 100) console.time(key) for (let i = 0; i < max; i++) { histogram.record(Math.floor((Math.random() * 42 + 1))) } console.timeEnd(key) console.log('80 percentile is', histogram.percentile(80)) console.log('99 percentile is', histogram.percentile(99)) console.log(histogram.percentiles()) ``` ## API * <a href="#histogram"><code>Histogram</code></a> * <a href="#record"><code>histogram#<b>record()</b></code></a> * <a href="#recordCorrectedValue"><code>histogram#<b>recordCorrectedValue()</b></code></a> * <a href="#min"><code>histogram#<b>min()</b></code></a> * <a href="#max"><code>histogram#<b>max()</b></code></a> * <a href="#mean"><code>histogram#<b>mean()</b></code></a> * <a href="#stddev"><code>histogram#<b>stddev()</b></code></a> * <a href="#percentile"><code>histogram#<b>percentile()</b></code></a> * <a href="#percentiles"><code>histogram#<b>percentiles()</b></code></a> * <a href="#linearcounts"><code>histogram#<b>linearcounts()</b></code></a> * <a href="#logcounts"><code>histogram#<b>logcounts()</b></code></a> * <a href="#recordedcounts"><code>histogram#<b>recordedcounts()</b></code></a> * <a href="#encode"><code>histogram#<b>encode()</b></code></a> * <a href="#decode"><code>histogram#<b>decode()</b></code></a> * <a href="#lowestEquivalentValue"><code>histogram#<b>lowestEquivalentValue()</b></code></a> * <a href="#highestEquivalentValue"><code>histogram#<b>highestEquivalentValue()</b></code></a> * <a href="#nextNonEquivalentValue"><code>histogram#<b>nextNonEquivalentValue()</b></code></a> * <a href="#areValuesEquivalent"><code>histogram#<b>areValuesEquivalent()</b></code></a> * <a href="#add"><code>histogram#<b>add()</b></code></a> * <a href="#reset"><code>histogram#<b>reset()</b></code></a> #### Properties * <a href="#lowestTrackableValue"><code>histogram#lowestTrackableValue</code></a> * <a href="#highestTrackableValue"><code>histogram#highestTrackableValue</code></a> * <a href="#significantFigures"><code>histogram#significantFigures</code></a> * <a href="#totalCount"><code>histogram#totalCount</code></a> * <a href="#memorySize"><code>histogram#memorySize</code></a> ------------------------------------------------------- <a name="histogram"></a> ### Histogram(lowest, max, figures) Create a new histogram with: * `lowest`: is the lowest possible number that can be recorded (default 1). * `max`: is the maximum number that can be recorded (default 100). * `figures`: the number of figures in a decimal number that will be maintained, must be between 1 and 5 (inclusive) (default 3). ------------------------------------------------------- <a name="record"></a> ### histogram.record(value, count = 1) Record `value` in the histogram with a count of `count`. Returns `true` if the recording was successful, `false` otherwise. ------------------------------------------------------- <a name="recordCorrectedValue"></a> ### histogram.recordCorrectedValue(value, expectedInterval, count = 1) Record `value` in the histogram with a count of `count` and backfill based on a `expectedInterval`. This is specifically used for recording latency. If `value` is larger than the `expectedInterval` then the latency recording system has experienced coordinated omission. This method fills in the values that would have occurred had the client providing the load not been blocked. Returns `true` if the recording was successful, `false` otherwise. ------------------------------------------------------- <a name="min"></a> ### histogram.min() Return the minimum value recorded in the histogram. ------------------------------------------------------- <a name="max"></a> ### histogram.max() Return the maximum value recorded in the histogram. ------------------------------------------------------- <a name="mean"></a> ### histogram.mean() Return the mean of the histogram. ------------------------------------------------------- <a name="stddev"></a> ### histogram.stddev() Return the standard deviation of the histogram. ------------------------------------------------------- <a name="percentile"></a> ### histogram.percentile(percentile) Returns the value at the given percentile. `percentile` must be > 0 and <= 100, otherwise it will throw. ------------------------------------------------------- <a name="percentiles"></a> ### histogram.percentiles() Returns all the percentiles. Sample output: ```js [ { percentile: 0, value: 1 }, { percentile: 50, value: 22 }, { percentile: 75, value: 32 }, { percentile: 87.5, value: 37 }, { percentile: 93.75, value: 40 }, { percentile: 96.875, value: 41 }, { percentile: 98.4375, value: 42 }, { percentile: 100, value: 42 } ] ``` ------------------------------------------------------- <a name="linearcounts"></a> ### histogram.linearcounts(valueUnitsPerBucket) Returns the recorded counts in "buckets" using `valueUnitsPerBucket` as the bucket size. Sample output: ```js [ { count: 10000, value: 99968 }, { count: 0, value: 199936 }, { count: 0, value: 299776 }, { count: 0, value: 399872 }, { count: 0, value: 499968 }, { count: 0, value: 599552 }, { count: 0, value: 699904 }, { count: 0, value: 799744 }, { count: 0, value: 899584 }, { count: 0, value: 999936 }, ... 990 more items ] ``` ------------------------------------------------------- <a name="logcounts"></a> ### histogram.logcounts(valueUnitsFirstBucket, logBase) Returns the recorded counts according to a logarithmic distribution using `valueUnitsFirstBucket` for the first value and increasing exponentially according to `logBase`. Sample output: ```js [ { count: 10000, value: 10000 }, { count: 0, value: 20000 }, { count: 0, value: 40000 }, { count: 0, value: 80000 }, { count: 0, value: 160000 }, { count: 0, value: 320000 }, { count: 0, value: 640000 }, { count: 0, value: 1280000 }, { count: 0, value: 2560000 }, { count: 0, value: 5120000 }, { count: 0, value: 10240000 }, { count: 0, value: 20480000 }, { count: 0, value: 40960000 }, { count: 0, value: 81920000 }, { count: 1, value: 163840000 } ] ``` ------------------------------------------------------- <a name="recordedcounts"></a> ### histogram.recordedcounts() Returns all the values recorded in the histogram. Sample output: ```js [ { count: 10000, value: 1000 }, { count: 1, value: 99942400 } ] ``` ------------------------------------------------------- <a name="encode"></a> ### histogram.encode() Returns a `Buffer` containing a serialized version of the histogram ------------------------------------------------------- <a name="decode"></a> ### histogram.decode(buf) Reads a `Buffer` and deserialize an histogram. ------------------------------------------------------- <a name="lowestEquivalentValue"></a> ### histogram.lowestEquivalentValue(value) Get the lowest value that is equivalent to the given value within the histogram's resolution, where "equivalent" means that value samples recorded for any two equivalent values are counted in a common total count. ------------------------------------------------------ <a name="highestEquivalentValue"></a> ### histogram.highestEquivalentValue(value) Get the highest value that is equivalent to the given value within the histogram's resolution, where "equivalent" means that value samples recorded for any two equivalent values are counted in a common total count. ------------------------------------------------------ <a name="nextNonEquivalentValue"></a> ### histogram.nextNonEquivalentValue(value) Get the next value that is not equivalent to the given value within the histogram's resolution. ------------------------------------------------------ <a name="areValuesEquivalent"></a> ### histogram.areValueEquivalent(value1, value2) Determine if two values are equivalent within the histogram's resolution where "equivalent" means that value samples recorded for any two equivalent values are counted in a common total count. ------------------------------------------------------- <a name="add"></a> ### histogram.add(other[, expectedIntervalBetweenValueSamples]) Adds all of the values from `other` to 'this' histogram. Will return the number of values that are dropped when copying. Values will be dropped if they around outside of `histogram.lowestTrackableValue` and `histogram.highestTrackableValue`. If `expectedIntervalBetweenValueSamples` is specified, values are backfilled with values that would have occurred had the client providing the load not been blocked. The values added will include an auto-generated additional series of decreasingly-smaller (down to the `expectedIntervalBetweenValueSamples`) value records for each count found in the current histogram that is larger than the `expectedIntervalBetweenValueSamples`. Returns the number of values dropped while copying. ------------------------------------------------------- <a name="reset"></a> ### histogram.reset() Resets the histogram so it can be reused. ------------------------------------------------------- <a name="properties"></a> ## Properties <a name="lowestTrackableValue"></a> ### histogram.lowestTrackableValue Get the configured lowestTrackableValue ------------------------------------------------------- <a name="highestTrackableValue"></a> ### histogram.highestTrackableValue Get the configured highestTrackableValue ------------------------------------------------------- <a name="significantFigures"></a> ### histogram.significantFigures Get the configured number of significant value digits ------------------------------------------------------- <a name="totalCount"></a> ### histogram.totalCount Gets the total number of recorded values. ------------------------------------------------------- <a name="#memorySize"></a> ### histogram.memorySize Get the memory size of the Histogram. ------------------------------------------------------- ## Acknowledgements This project was kindly sponsored by [nearForm](http://nearform.com). ## License This library is licensed as MIT HdrHistogram_c is licensed as [BSD license][HdrHistogram_c-license] zlib is licensed as [zlib License][zlib-license] [hdr]: http://hdrhistogram.org/ [cimpl]: https://github.com/HdrHistogram/HdrHistogram_c [node-gyp]: https://github.com/nodejs/node-gyp#installation [mapbox]: http://mapbox.com [node-pre-gyp]: https://github.com/mapbox/node-pre-gyp [sqlite3]: https://github.com/mapbox/node-sqlite3 [HdrHistogram_c-license]: https://github.com/HdrHistogram/HdrHistogram_c/blob/master/LICENSE.txt [sqlite3-scripts-license]: https://github.com/mapbox/node-sqlite3/blob/master/LICENSE [zlib-license]: http://www.zlib.net/zlib_license.html