Skip to content

Commit 48a32c9

Browse files
committed
fix bugs on add & subtract
1 parent 8f7db99 commit 48a32c9

File tree

4 files changed

+51
-47
lines changed

4 files changed

+51
-47
lines changed

assembly/Histogram.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,10 @@ export default class Histogram<T, U> extends AbstractHistogramBase<T, U> {
672672
otherHistogram.maxValue
673673
);
674674
let otherCount = otherHistogram.getCountAtIndex(otherMaxIndex);
675-
this.recordCountAtValue(otherCount, otherHistogram.maxValue);
675+
this.recordCountAtValue(
676+
otherCount,
677+
otherHistogram.valueFromIndex(otherMaxIndex)
678+
);
676679

677680
// Record the remaining values, up to but not including the max value:
678681
for (let i = 0; i < otherMaxIndex; i++) {
@@ -756,12 +759,15 @@ export default class Histogram<T, U> extends AbstractHistogramBase<T, U> {
756759
) {
757760
// optim
758761
// Counts arrays are of the same length and meaning, so we can just iterate and add directly:
762+
let observedOtherTotalCount: u64 = 0;
759763
for (let i = 0; i < otherHistogram.countsArrayLength; i++) {
760764
const otherCount = otherHistogram.getCountAtIndex(i);
761765
if (otherCount > 0) {
762766
this.addToCountAtIndex(i, -otherCount);
767+
observedOtherTotalCount += otherCount;
763768
}
764769
}
770+
this.totalCount = this.totalCount - observedOtherTotalCount;
765771
} else {
766772
for (let i = 0; i < otherHistogram.countsArrayLength; i++) {
767773
const otherCount = otherHistogram.getCountAtIndex(i);

assembly/__tests__/Histogram.spec.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ describe("Histogram correcting coordinated omissions", () => {
285285
});
286286
});
287287

288-
describe("Histogram add & substract", () => {
288+
describe("Histogram add & subtract", () => {
289289
it("should add histograms of same size", () => {
290290
// given
291291
const histogram = buildHistogram();
@@ -317,16 +317,33 @@ describe("Histogram add & substract", () => {
317317
// given
318318
const histogram = buildHistogram();
319319
const histogram2 = buildHistogram();
320-
histogram.autoResize = true;
321-
histogram.recordValue(1000);
322-
histogram2.recordValue(42000);
320+
histogram.recordCountAtValue(2, 100);
321+
histogram2.recordCountAtValue(1, 100);
322+
histogram.recordCountAtValue(2, 200);
323+
histogram2.recordCountAtValue(1, 200);
324+
histogram.recordCountAtValue(2, 300);
325+
histogram2.recordCountAtValue(1, 300);
323326
const outputBefore = histogram.outputPercentileDistribution();
324327
// when
325328
histogram.add<Storage<Uint8Array, u8>, u8>(histogram2);
326329
histogram.subtract<Storage<Uint8Array, u8>, u8>(histogram2);
327330
// then
328331
expect(histogram.outputPercentileDistribution()).toBe(outputBefore);
329332
});
333+
334+
it("should be equal when another histogram of lower precision is added then subtracted", () => {
335+
// given
336+
const histogram = new Histogram8(1, 1000000000, 5);
337+
const histogram2 = new Histogram8(1, 1000000000, 3);
338+
histogram.recordValue(10);
339+
histogram2.recordValue(100000);
340+
// when
341+
const outputBefore = histogram.outputPercentileDistribution();
342+
histogram.add<Storage<Uint8Array, u8>, u8>(histogram2);
343+
histogram.subtract<Storage<Uint8Array, u8>, u8>(histogram2);
344+
// then
345+
expect(histogram.outputPercentileDistribution()).toBe(outputBefore);
346+
});
330347
});
331348

332349
describe("Packed Histogram", () => {

src/Histogram.spec.ts

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -474,60 +474,35 @@ describe("Histogram add & substract", () => {
474474
expect(histogram.totalCount).toBe(2);
475475
expect(Math.floor(histogram.mean / 100)).toBe(215);
476476
});
477-
it("should add histograms of different sizes b", () => {
478-
// given
479-
const histogram = new Int32Histogram(1, Number.MAX_SAFE_INTEGER, 2);
480-
const histogram2 = new Int32Histogram(1, 1024, 2);
481-
histogram2.autoResize = true;
482-
histogram.recordValue(42000);
483-
histogram2.recordValue(1000);
484-
// when
485-
histogram.add(histogram2);
486-
// then
487-
expect(histogram.totalCount).toBe(2);
488-
expect(Math.floor(histogram.mean / 100)).toBe(215);
489-
});
490477

491-
it("should be equal when another histogram is added then subtracted", () => {
478+
it("should be equal when another histogram of lower precision is added then subtracted", () => {
492479
// given
493-
const histogram = new Int8Histogram(1, 1024, 3);
494-
const histogram2 = new Int8Histogram(1, 1024, 3);
495-
histogram.autoResize = true;
480+
const histogram = build({ numberOfSignificantValueDigits: 5 });
481+
const histogram2 = build({ numberOfSignificantValueDigits: 3 });
496482
histogram.recordValue(100);
497-
histogram2.recordValue(420);
498-
const outputBefore = histogram.outputPercentileDistribution();
483+
histogram2.recordValue(42000);
499484
// when
485+
const before = histogram.summary;
500486
histogram.add(histogram2);
501487
histogram.subtract(histogram2);
502488
// then
503-
expect(histogram.outputPercentileDistribution()).toBe(outputBefore);
489+
expect(histogram.summary).toStrictEqual(before);
504490
});
505491

506-
it("should be equal when another wasm histogram is added then subtracted", () => {
492+
it("should update percentiles when another histogram of same characteristics is substracted", () => {
507493
// given
508-
const histogram = build({
509-
lowestDiscernibleValue: 1,
510-
highestTrackableValue: 1024,
511-
autoResize: true,
512-
numberOfSignificantValueDigits: 5,
513-
bitBucketSize: 32,
514-
useWebAssembly: true,
515-
});
516-
const histogram2 = build({
517-
lowestDiscernibleValue: 1,
518-
highestTrackableValue: Number.MAX_SAFE_INTEGER,
519-
numberOfSignificantValueDigits: 5,
520-
bitBucketSize: 32,
521-
useWebAssembly: true,
522-
});
523-
histogram.recordValue(1000);
524-
histogram2.recordValue(42000);
525-
const outputBefore = histogram.outputPercentileDistribution();
494+
const histogram = build({ numberOfSignificantValueDigits: 3 });
495+
const histogram2 = build({ numberOfSignificantValueDigits: 3 });
496+
histogram.recordValueWithCount(100, 2);
497+
histogram2.recordValueWithCount(100, 1);
498+
histogram.recordValueWithCount(200, 2);
499+
histogram2.recordValueWithCount(200, 1);
500+
histogram.recordValueWithCount(300, 2);
501+
histogram2.recordValueWithCount(300, 1);
526502
// when
527-
histogram.add(histogram2);
528503
histogram.subtract(histogram2);
529504
// then
530-
expect(histogram.outputPercentileDistribution()).toBe(outputBefore);
505+
expect(histogram.getValueAtPercentile(50)).toBe(200);
531506
});
532507
});
533508

src/JsHistogram.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,10 @@ export abstract class JsHistogram implements Histogram {
956956
otherHistogram.maxValue
957957
);
958958
let otherCount = otherHistogram.getCountAtIndex(otherMaxIndex);
959-
this.recordCountAtValue(otherCount, otherHistogram.maxValue);
959+
this.recordCountAtValue(
960+
otherCount,
961+
otherHistogram.valueFromIndex(otherMaxIndex)
962+
);
960963

961964
// Record the remaining values, up to but not including the max value:
962965
for (let i = 0; i < otherMaxIndex; i++) {
@@ -1027,12 +1030,15 @@ export abstract class JsHistogram implements Histogram {
10271030
) {
10281031
// optim
10291032
// Counts arrays are of the same length and meaning, so we can just iterate and add directly:
1033+
let observedOtherTotalCount = 0;
10301034
for (let i = 0; i < otherHistogram.countsArrayLength; i++) {
10311035
const otherCount = otherHistogram.getCountAtIndex(i);
10321036
if (otherCount > 0) {
10331037
this.addToCountAtIndex(i, -otherCount);
1038+
observedOtherTotalCount += otherCount;
10341039
}
10351040
}
1041+
this.setTotalCount(this.totalCount - observedOtherTotalCount);
10361042
} else {
10371043
for (let i = 0; i < otherHistogram.countsArrayLength; i++) {
10381044
const otherCount = otherHistogram.getCountAtIndex(i);

0 commit comments

Comments
 (0)