NET-Web-API-w-Angular/my-app/node_modules/hdr-histogram-js/dist/Histogram.spec.js

473 lines
19 KiB
JavaScript
Raw Normal View History

2024-02-09 00:38:41 +00:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const _1 = require(".");
const JsHistogram_1 = require("./JsHistogram");
const Histogram_1 = require("./Histogram");
const Int32Histogram_1 = require("./Int32Histogram");
const wasm_1 = require("./wasm");
class HistogramForTests extends JsHistogram_1.default {
//constructor() {}
clearCounts() { }
incrementCountAtIndex(index) { }
incrementTotalCount() { }
addToTotalCount(value) { }
setTotalCount(totalCount) { }
resize(newHighestTrackableValue) {
this.establishSize(newHighestTrackableValue);
}
addToCountAtIndex(index, value) { }
setCountAtIndex(index, value) { }
getTotalCount() {
return 0;
}
getCountAtIndex(index) {
return 0;
}
_getEstimatedFootprintInBytes() {
return 42;
}
copyCorrectedForCoordinatedOmission(expectedIntervalBetweenValueSamples) {
return this;
}
}
describe("Histogram initialization", () => {
let histogram;
beforeEach(() => {
histogram = new HistogramForTests(1, Number.MAX_SAFE_INTEGER, 3);
});
it("should set sub bucket size", () => {
expect(histogram.subBucketCount).toBe(2048);
});
it("should set resize to false when max value specified", () => {
expect(histogram.autoResize).toBe(false);
});
it("should compute counts array length", () => {
expect(histogram.countsArrayLength).toBe(45056);
});
it("should compute bucket count", () => {
expect(histogram.bucketCount).toBe(43);
});
it("should set min non zero value", () => {
expect(histogram.minNonZeroValue).toBe(Number.MAX_SAFE_INTEGER);
});
it("should set max value", () => {
expect(histogram.maxValue).toBe(0);
});
});
describe("Histogram recording values", () => {
it("should compute count index when value in first bucket", () => {
// given
const histogram = new HistogramForTests(1, Number.MAX_SAFE_INTEGER, 3);
// when
const index = histogram.countsArrayIndex(2000); // 2000 < 2048
expect(index).toBe(2000);
});
it("should compute count index when value outside first bucket", () => {
// given
const histogram = new HistogramForTests(1, Number.MAX_SAFE_INTEGER, 3);
// when
const index = histogram.countsArrayIndex(2050); // 2050 > 2048
// then
expect(index).toBe(2049);
});
it("should compute count index taking into account lowest discernible value", () => {
// given
const histogram = new HistogramForTests(2000, Number.MAX_SAFE_INTEGER, 2);
// when
const index = histogram.countsArrayIndex(16000);
// then
expect(index).toBe(15);
});
it("should compute count index of a big value taking into account lowest discernible value", () => {
// given
const histogram = new HistogramForTests(2000, Number.MAX_SAFE_INTEGER, 2);
// when
const bigValue = Number.MAX_SAFE_INTEGER - 1;
const index = histogram.countsArrayIndex(bigValue);
// then
expect(index).toBe(4735);
});
it("should update min non zero value", () => {
// given
const histogram = new HistogramForTests(1, Number.MAX_SAFE_INTEGER, 3);
// when
histogram.recordValue(123);
// then
expect(histogram.minNonZeroValue).toBe(123);
});
it("should update max value", () => {
// given
const histogram = new HistogramForTests(1, Number.MAX_SAFE_INTEGER, 3);
// when
histogram.recordValue(123);
// then
expect(histogram.maxValue).toBe(123);
});
it("should throw an error when value bigger than highest trackable value", () => {
// given
const histogram = new HistogramForTests(1, 4096, 3);
// when then
expect(() => histogram.recordValue(9000)).toThrowError();
});
it("should not throw an error when autoresize enable and value bigger than highest trackable value", () => {
// given
const histogram = new HistogramForTests(1, 4096, 3);
histogram.autoResize = true;
// when then
expect(() => histogram.recordValue(9000)).not.toThrowError();
});
it("should increase counts array size when recording value bigger than highest trackable value", () => {
// given
const histogram = new HistogramForTests(1, 4096, 3);
histogram.autoResize = true;
// when
histogram.recordValue(9000);
// then
expect(histogram.highestTrackableValue).toBeGreaterThan(9000);
});
});
describe("Histogram computing statistics", () => {
const histogram = new Int32Histogram_1.default(1, Number.MAX_SAFE_INTEGER, 3);
it("should compute mean value", () => {
// given
histogram.reset();
// when
histogram.recordValue(25);
histogram.recordValue(50);
histogram.recordValue(75);
// then
expect(histogram.mean).toBe(50);
});
it("should compute standard deviation", () => {
// given
histogram.reset();
// when
histogram.recordValue(25);
histogram.recordValue(50);
histogram.recordValue(75);
// then
expect(histogram.stdDeviation).toBeGreaterThan(20.4124);
expect(histogram.stdDeviation).toBeLessThan(20.4125);
});
it("should compute percentile distribution", () => {
// given
histogram.reset();
// when
histogram.recordValue(25);
histogram.recordValue(50);
histogram.recordValue(75);
// then
const expectedResult = ` Value Percentile TotalCount 1/(1-Percentile)
25.000 0.000000000000 1 1.00
25.000 0.100000000000 1 1.11
25.000 0.200000000000 1 1.25
25.000 0.300000000000 1 1.43
50.000 0.400000000000 2 1.67
50.000 0.500000000000 2 2.00
50.000 0.550000000000 2 2.22
50.000 0.600000000000 2 2.50
50.000 0.650000000000 2 2.86
75.000 0.700000000000 3 3.33
75.000 1.000000000000 3
#[Mean = 50.000, StdDeviation = 20.412]
#[Max = 75.000, Total count = 3]
#[Buckets = 43, SubBuckets = 2048]
`;
expect(histogram.outputPercentileDistribution()).toBe(expectedResult);
});
it("should compute percentile distribution in csv format", () => {
// given
histogram.reset();
// when
histogram.recordValue(25);
histogram.recordValue(50);
histogram.recordValue(75);
// then
const expectedResult = `"Value","Percentile","TotalCount","1/(1-Percentile)"
25.000,0.000000000000,1,1.00
25.000,0.100000000000,1,1.11
25.000,0.200000000000,1,1.25
25.000,0.300000000000,1,1.43
50.000,0.400000000000,2,1.67
50.000,0.500000000000,2,2.00
50.000,0.550000000000,2,2.22
50.000,0.600000000000,2,2.50
50.000,0.650000000000,2,2.86
75.000,0.700000000000,3,3.33
75.000,1.000000000000,3,Infinity
`;
expect(histogram.outputPercentileDistribution(undefined, undefined, true)).toBe(expectedResult);
});
it("should compute percentile distribution in JSON format with rounding according to number of significant digits", () => {
// given
histogram.reset();
// when
histogram.recordValue(25042);
histogram.recordValue(50042);
histogram.recordValue(75042);
// then
const { summary } = histogram;
expect(summary.p50).toEqual(50000);
});
});
describe("Histogram correcting coordinated omissions", () => {
const histogram = new Int32Histogram_1.default(1, Number.MAX_SAFE_INTEGER, 3);
it("should generate additional values when recording", () => {
// given
histogram.reset();
// when
histogram.recordValueWithExpectedInterval(207, 100);
// then
expect(histogram.totalCount).toBe(2);
expect(histogram.minNonZeroValue).toBe(107);
expect(histogram.maxValue).toBe(207);
});
it("should generate additional values when correcting after recording", () => {
// given
histogram.reset();
histogram.recordValue(207);
histogram.recordValue(207);
// when
const correctedHistogram = histogram.copyCorrectedForCoordinatedOmission(100);
// then
expect(correctedHistogram.totalCount).toBe(4);
expect(correctedHistogram.minNonZeroValue).toBe(107);
expect(correctedHistogram.maxValue).toBe(207);
});
it("should not generate additional values when correcting after recording", () => {
// given
histogram.reset();
histogram.recordValue(207);
histogram.recordValue(207);
// when
const correctedHistogram = histogram.copyCorrectedForCoordinatedOmission(1000);
// then
expect(correctedHistogram.totalCount).toBe(2);
expect(correctedHistogram.minNonZeroValue).toBe(207);
expect(correctedHistogram.maxValue).toBe(207);
});
});
describe("WASM Histogram not initialized", () => {
it("should throw a clear error message", () => {
expect(() => _1.build({ useWebAssembly: true })).toThrow("WebAssembly is not ready yet");
expect(() => wasm_1.WasmHistogram.build()).toThrow("WebAssembly is not ready yet");
expect(() => wasm_1.WasmHistogram.decode(null)).toThrow("WebAssembly is not ready yet");
});
});
describe("WASM Histogram not happy path", () => {
beforeEach(wasm_1.initWebAssemblySync);
it("should throw a clear error message when used after destroy", () => {
const destroyedHistogram = _1.build({ useWebAssembly: true });
destroyedHistogram.destroy();
expect(() => destroyedHistogram.recordValue(42)).toThrow("Cannot use a destroyed histogram");
});
it("should not crash when displayed after destroy", () => {
const destroyedHistogram = _1.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 = _1.build({ useWebAssembly: true });
const jsHistogram = _1.build({ useWebAssembly: false });
expect(() => jsHistogram.add(wasmHistogram)).toThrow("Cannot add a WASM histogram to a regular JS histogram");
});
it("should throw a clear error message when trying to add a JS regular Histogram", () => {
const wasmHistogram = _1.build({ useWebAssembly: true });
const jsHistogram = _1.build({ useWebAssembly: false });
expect(() => wasmHistogram.add(jsHistogram)).toThrow("Cannot add a regular JS histogram to a WASM histogram");
});
it("should throw a clear error message when substracted to a JS regular Histogram", () => {
const wasmHistogram = _1.build({ useWebAssembly: true });
const jsHistogram = _1.build({ useWebAssembly: false });
expect(() => jsHistogram.subtract(wasmHistogram)).toThrow("Cannot subtract a WASM histogram to a regular JS histogram");
});
it("should throw a clear error message when trying to add a JS regular Histogram", () => {
const wasmHistogram = _1.build({ useWebAssembly: true });
const jsHistogram = _1.build({ useWebAssembly: false });
expect(() => wasmHistogram.subtract(jsHistogram)).toThrow("Cannot subtract a regular JS histogram to a WASM histogram");
});
});
describe("WASM estimated memory footprint", () => {
let wasmHistogram;
beforeAll(wasm_1.initWebAssembly);
afterEach(() => wasmHistogram.destroy());
it("should be a little bit more than js footprint for packed histograms", () => {
wasmHistogram = _1.build({ useWebAssembly: true, bitBucketSize: "packed" });
expect(wasmHistogram.estimatedFootprintInBytes).toBeGreaterThan(_1.build({ bitBucketSize: "packed" }).estimatedFootprintInBytes);
});
});
describe("WASM Histogram correcting coordinated omissions", () => {
let histogram;
beforeAll(wasm_1.initWebAssembly);
beforeEach(() => {
histogram = _1.build({ useWebAssembly: true });
});
afterEach(() => histogram.destroy());
it("should generate additional values when recording", () => {
// given
histogram.reset();
// when
histogram.recordValueWithExpectedInterval(207, 100);
// then
expect(histogram.totalCount).toBe(2);
expect(histogram.minNonZeroValue).toBe(107);
expect(histogram.maxValue).toBe(207);
});
it("should generate additional values when correcting after recording", () => {
// given
histogram.reset();
histogram.recordValue(207);
histogram.recordValue(207);
// when
const correctedHistogram = histogram.copyCorrectedForCoordinatedOmission(100);
// then
expect(correctedHistogram.totalCount).toBe(4);
expect(correctedHistogram.minNonZeroValue).toBe(107);
expect(correctedHistogram.maxValue).toBe(207);
});
it("should not generate additional values when correcting after recording", () => {
// given
histogram.reset();
histogram.recordValue(207);
histogram.recordValue(207);
// when
const correctedHistogram = histogram.copyCorrectedForCoordinatedOmission(1000);
// then
expect(correctedHistogram.totalCount).toBe(2);
expect(correctedHistogram.minNonZeroValue).toBe(207);
expect(correctedHistogram.maxValue).toBe(207);
});
});
describe("Histogram add & substract", () => {
beforeAll(wasm_1.initWebAssembly);
it("should add histograms of same size", () => {
// given
const histogram = new Int32Histogram_1.default(1, Number.MAX_SAFE_INTEGER, 2);
const histogram2 = new Int32Histogram_1.default(1, Number.MAX_SAFE_INTEGER, 2);
histogram.recordValue(42);
histogram2.recordValue(158);
// when
histogram.add(histogram2);
// then
expect(histogram.totalCount).toBe(2);
expect(histogram.mean).toBe(100);
});
it("should add histograms of different sizes & precisions", () => {
// given
const histogram = _1.build({
lowestDiscernibleValue: 1,
highestTrackableValue: 1024,
autoResize: true,
numberOfSignificantValueDigits: 2,
bitBucketSize: "packed",
useWebAssembly: true,
});
const histogram2 = _1.build({
lowestDiscernibleValue: 1,
highestTrackableValue: 1024,
autoResize: true,
numberOfSignificantValueDigits: 3,
bitBucketSize: 32,
useWebAssembly: true,
});
//histogram2.autoResize = true;
histogram.recordValue(42000);
histogram2.recordValue(1000);
// when
histogram.add(histogram2);
// then
expect(histogram.totalCount).toBe(2);
expect(Math.floor(histogram.mean / 100)).toBe(215);
});
it("should add histograms of different sizes", () => {
// given
const histogram = new Int32Histogram_1.default(1, Number.MAX_SAFE_INTEGER, 2);
const histogram2 = new Int32Histogram_1.default(1, 1024, 2);
histogram2.autoResize = true;
histogram.recordValue(42000);
histogram2.recordValue(1000);
// when
histogram.add(histogram2);
// then
expect(histogram.totalCount).toBe(2);
expect(Math.floor(histogram.mean / 100)).toBe(215);
});
it("should be equal when another histogram of lower precision is added then subtracted", () => {
// given
const histogram = _1.build({ numberOfSignificantValueDigits: 5 });
const histogram2 = _1.build({ numberOfSignificantValueDigits: 3 });
histogram.recordValue(100);
histogram2.recordValue(42000);
// when
const before = histogram.summary;
histogram.add(histogram2);
histogram.subtract(histogram2);
// then
expect(histogram.summary).toStrictEqual(before);
});
it("should update percentiles when another histogram of same characteristics is substracted", () => {
// given
const histogram = _1.build({ numberOfSignificantValueDigits: 3 });
const histogram2 = _1.build({ numberOfSignificantValueDigits: 3 });
histogram.recordValueWithCount(100, 2);
histogram2.recordValueWithCount(100, 1);
histogram.recordValueWithCount(200, 2);
histogram2.recordValueWithCount(200, 1);
histogram.recordValueWithCount(300, 2);
histogram2.recordValueWithCount(300, 1);
// when
histogram.subtract(histogram2);
// then
expect(histogram.getValueAtPercentile(50)).toBe(200);
});
});
describe("Histogram clearing support", () => {
beforeAll(wasm_1.initWebAssembly);
it("should reset data in order to reuse histogram", () => {
// given
const histogram = _1.build({
lowestDiscernibleValue: 1,
highestTrackableValue: Number.MAX_SAFE_INTEGER,
numberOfSignificantValueDigits: 5,
useWebAssembly: true,
});
histogram.startTimeStampMsec = 42;
histogram.endTimeStampMsec = 56;
histogram.tag = "blabla";
histogram.recordValue(1000);
// when
histogram.reset();
// then
expect(histogram.totalCount).toBe(0);
expect(histogram.startTimeStampMsec).toBe(0);
expect(histogram.endTimeStampMsec).toBe(0);
expect(histogram.tag).toBe(Histogram_1.NO_TAG);
expect(histogram.maxValue).toBe(0);
expect(histogram.minNonZeroValue).toBeGreaterThan(Number.MAX_SAFE_INTEGER);
expect(histogram.getValueAtPercentile(99.999)).toBe(0);
});
it("should behave as new when reseted", () => {
// given
const histogram = _1.build({
lowestDiscernibleValue: 1,
highestTrackableValue: 15000,
numberOfSignificantValueDigits: 2,
});
const histogram2 = _1.build({
lowestDiscernibleValue: 1,
highestTrackableValue: 15000,
numberOfSignificantValueDigits: 2,
});
histogram.recordValue(1);
histogram.recordValue(100);
histogram.recordValue(2000);
histogram.reset();
// when
histogram.recordValue(1000);
histogram2.recordValue(1000);
// then
expect(histogram.mean).toBe(histogram2.mean);
});
});
//# sourceMappingURL=Histogram.spec.js.map