Skip to content

Commit

Permalink
histogram summary feature
Browse files Browse the repository at this point in the history
  • Loading branch information
alexvictoor committed Jul 21, 2020
1 parent 23cb642 commit a509561
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 18 deletions.
33 changes: 27 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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

Expand Down Expand Up @@ -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"
Expand Down
9 changes: 7 additions & 2 deletions src/Histogram.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});

Expand Down Expand Up @@ -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 });
Expand Down
7 changes: 6 additions & 1 deletion src/Histogram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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 {
Expand Down
8 changes: 6 additions & 2 deletions src/JsHistogram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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() {
Expand Down
10 changes: 5 additions & 5 deletions src/bench/histogram-json-percentile.ts
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -19,7 +19,7 @@ initWebAssembly().then(() => {
histogram.recordValueWithCount(randomInteger(), randomInteger(100));
}
return () => {
toJSON(histogram);
toSummary(histogram);
};
},
options
Expand All @@ -36,7 +36,7 @@ initWebAssembly().then(() => {
histogram.recordValueWithCount(randomInteger(), randomInteger(100));
}
return () => {
toJSON(histogram);
toSummary(histogram);
};
},
options
Expand All @@ -51,7 +51,7 @@ initWebAssembly().then(() => {
histogram.recordValueWithCount(randomInteger(), randomInteger(100));
}
return () => {
toJSON(histogram);
toSummary(histogram);
};
},
options
Expand All @@ -67,7 +67,7 @@ initWebAssembly().then(() => {
histogram.recordValueWithCount(randomInteger(), randomInteger(100));
}
return () => {
toJSON(histogram);
toSummary(histogram);
};
},
options
Expand Down
15 changes: 13 additions & 2 deletions src/wasm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BINARY } from "./generated-wasm";
import Histogram, {
NO_TAG,
BitBucketSize,
toJSON,
toSummary,
HistogramSummary
} from "../Histogram";
// @ts-ignore
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit a509561

Please sign in to comment.