diff --git a/README.md b/README.md index 5d14e9e..ea3a2f7 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,7 @@ not have any surprise though. ## Instantiate an histogram -The API is very close to the original Java API, there is just -a tiny addition, a simple builder function. -Here is how to use it to instantiate a new histogram instance: +HdrHistogramJS provides several histogram implementations. The simplest way to get a new histogram instance is to use the _build()_ function. Here is how to use it: ``` import * as hdr from "hdr-histogram-js" @@ -84,7 +82,7 @@ const histogram ``` -BitBucketSize 'packed' options is available since HdrHistogramJS v1.2 . Like the Java packed implementtation, it has a very low memory footprint but it is way slower than original 'unpacked' implementations. +BitBucketSize 'packed' options is available since HdrHistogramJS v1.2 . Like the Java packed implementation, it has a very low memory footprint but it is way slower than regular bucket based implementation. ## Record values and retrieve metrics @@ -113,15 +111,38 @@ h.recordValue(1244); console.log(h.minNonZeroValue); // 122 console.log(h.maxValue); // 1244 -console.log(h.getMean()); // 486.333... +console.log(h.mean); // 486.333... console.log(h.getValueAtPercentile(90)); // 1244 as well +console.log(h.summary); // { "p50": 123, ... , max: 1244, totalCount: 3 } ``` If youn need a live example you can also take alook at this [simple ping demo](https://hdrhistogram.github.io/HdrHistogramJSDemo/ping-demo.html) or this [HdrHistogramJS on HdrHistogramJS demo](https://hdrhistogram.github.io/HdrHistogramJSDemo/hdr-on-hdr.html). -As with the original Java version, you can also generate a textual +You can also very easily generate a textual representation of an histogram: +``` +console.log(`Statistics ${h}`); + +// output will be: +// +// Statistics Histogram 32b { +// "p50": 123, +// "p75": 1240, +// "p90": 1240, +// "p97_5": 1240, +// "p99": 1240, +// "p99_9": 1240, +// "p99_99": 1240, +// "p99_999": 1240, +// "max": 1244, +// "totalCount": 3 +// } + +``` + +You can also general an exhaustive textual representation similar to the one generated by the original Java HdrHistogram implementation: + ``` import * as hdr from "hdr-histogram-js" diff --git a/src/Histogram.spec.ts b/src/Histogram.spec.ts index fc1b483..92cf9ab 100644 --- a/src/Histogram.spec.ts +++ b/src/Histogram.spec.ts @@ -246,8 +246,8 @@ describe("Histogram computing statistics", () => { histogram.recordValue(50042); histogram.recordValue(75042); // then - const serializedHistogramData = JSON.parse(JSON.stringify(histogram)); - expect(serializedHistogramData.p50).toEqual(50000); + const { summary } = histogram; + expect(summary.p50).toEqual(50000); }); }); @@ -317,6 +317,11 @@ describe("WASM Histogram not happy path", () => { "Cannot use a destroyed histogram" ); }); + it("should not crash when displayed after destroy", () => { + const destroyedHistogram = build({ useWebAssembly: true }); + destroyedHistogram.destroy(); + expect(destroyedHistogram + "").toEqual("Destroyed WASM histogram"); + }); it("should throw a clear error message when added to a JS regular Histogram", () => { const wasmHistogram = build({ useWebAssembly: true }); const jsHistogram = build({ useWebAssembly: false }); diff --git a/src/Histogram.ts b/src/Histogram.ts index 61a48b7..b448861 100644 --- a/src/Histogram.ts +++ b/src/Histogram.ts @@ -43,6 +43,11 @@ export default interface Histogram { */ readonly mean: number; + /** + * Main percentiles, max value and total number of recorded values + */ + readonly summary: HistogramSummary; + /** * A (conservatively high) estimate of the Histogram's total footprint in bytes */ @@ -232,7 +237,7 @@ export interface HistogramConstructor { ): Histogram; } -export const toJSON = (histogram: Histogram): HistogramSummary => { +export const toSummary = (histogram: Histogram): HistogramSummary => { const { totalCount, maxValue, numberOfSignificantValueDigits } = histogram; const round = keepSignificantDigits(numberOfSignificantValueDigits); return { diff --git a/src/JsHistogram.ts b/src/JsHistogram.ts index 817071c..a2d2adf 100644 --- a/src/JsHistogram.ts +++ b/src/JsHistogram.ts @@ -10,7 +10,7 @@ import PercentileIterator from "./PercentileIterator"; import HistogramIterationValue from "./HistogramIterationValue"; import { integerFormatter, floatFormatter } from "./formatters"; import ulp from "./ulp"; -import Histogram, { NO_TAG, toJSON, HistogramSummary } from "./Histogram"; +import Histogram, { NO_TAG, toSummary, HistogramSummary } from "./Histogram"; const { pow, floor, ceil, log2, max, min } = Math; @@ -718,8 +718,12 @@ export abstract class JsHistogram implements Histogram { return result; } + get summary(): HistogramSummary { + return toSummary(this); + } + toJSON(): HistogramSummary { - return toJSON(this); + return this.summary; } inspect() { diff --git a/src/bench/histogram-json-percentile.ts b/src/bench/histogram-json-percentile.ts index 5e30679..1e12309 100644 --- a/src/bench/histogram-json-percentile.ts +++ b/src/bench/histogram-json-percentile.ts @@ -1,7 +1,7 @@ import b from "benny"; import { build } from "../index"; import { initWebAssembly } from "../wasm"; -import { toJSON } from "../Histogram"; +import { toSummary } from "../Histogram"; initWebAssembly().then(() => { const randomInteger = (max: number = Number.MAX_SAFE_INTEGER) => Math.floor(Math.random() * max); @@ -19,7 +19,7 @@ initWebAssembly().then(() => { histogram.recordValueWithCount(randomInteger(), randomInteger(100)); } return () => { - toJSON(histogram); + toSummary(histogram); }; }, options @@ -36,7 +36,7 @@ initWebAssembly().then(() => { histogram.recordValueWithCount(randomInteger(), randomInteger(100)); } return () => { - toJSON(histogram); + toSummary(histogram); }; }, options @@ -51,7 +51,7 @@ initWebAssembly().then(() => { histogram.recordValueWithCount(randomInteger(), randomInteger(100)); } return () => { - toJSON(histogram); + toSummary(histogram); }; }, options @@ -67,7 +67,7 @@ initWebAssembly().then(() => { histogram.recordValueWithCount(randomInteger(), randomInteger(100)); } return () => { - toJSON(histogram); + toSummary(histogram); }; }, options diff --git a/src/wasm/index.ts b/src/wasm/index.ts index 3d870ee..ef66efd 100644 --- a/src/wasm/index.ts +++ b/src/wasm/index.ts @@ -2,7 +2,7 @@ import { BINARY } from "./generated-wasm"; import Histogram, { NO_TAG, BitBucketSize, - toJSON, + toSummary, HistogramSummary } from "../Histogram"; // @ts-ignore @@ -210,11 +210,22 @@ export class WasmHistogram implements Histogram { ); } + private isDestroyed() { + return this._wasmHistogram === destroyedWasmHistogram; + } + + get summary(): HistogramSummary { + return toSummary(this); + } + toJSON(): HistogramSummary { - return toJSON(this); + return this.summary; } toString() { + if (this.isDestroyed()) { + return "Destroyed WASM histogram"; + } return `WASM ${this._remoteHistogramClass} ${JSON.stringify( this, null,