diff --git a/libs/exponential-histogram/src/main/java/org/elasticsearch/exponentialhistogram/ExponentialHistogram.java b/libs/exponential-histogram/src/main/java/org/elasticsearch/exponentialhistogram/ExponentialHistogram.java index 5b215e8120891..3bb3856f0e97a 100644 --- a/libs/exponential-histogram/src/main/java/org/elasticsearch/exponentialhistogram/ExponentialHistogram.java +++ b/libs/exponential-histogram/src/main/java/org/elasticsearch/exponentialhistogram/ExponentialHistogram.java @@ -216,6 +216,16 @@ static ExponentialHistogramBuilder builder(int scale, ExponentialHistogramCircui return new ExponentialHistogramBuilder(scale, breaker); } + /** + * Create a builder for an exponential histogram, which is initialized to copy the given histogram. + * @param toCopy the histogram to copy + * @param breaker the circuit breaker to use + * @return a new builder + */ + static ExponentialHistogramBuilder builder(ExponentialHistogram toCopy, ExponentialHistogramCircuitBreaker breaker) { + return new ExponentialHistogramBuilder(toCopy, breaker); + } + /** * Creates a histogram representing the distribution of the given values with at most the given number of buckets. * If the given {@code maxBucketCount} is greater than or equal to the number of values, the resulting histogram will have a diff --git a/libs/exponential-histogram/src/main/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramBuilder.java b/libs/exponential-histogram/src/main/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramBuilder.java index 60ba873409c1f..5ed3f37f16476 100644 --- a/libs/exponential-histogram/src/main/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramBuilder.java +++ b/libs/exponential-histogram/src/main/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramBuilder.java @@ -27,13 +27,13 @@ /** * A builder for building a {@link ReleasableExponentialHistogram} directly from buckets. - * Note that this class is not optimized regarding memory allocations, so it is not intended for high-throughput usage. + * Note that this class is not optimized regarding memory allocations or performance, so it is not intended for high-throughput usage. */ public class ExponentialHistogramBuilder { private final ExponentialHistogramCircuitBreaker breaker; - private final int scale; + private int scale; private ZeroBucket zeroBucket = ZeroBucket.minimalEmpty(); private Double sum; private Double min; @@ -47,6 +47,29 @@ public class ExponentialHistogramBuilder { this.scale = scale; } + ExponentialHistogramBuilder(ExponentialHistogram toCopy, ExponentialHistogramCircuitBreaker breaker) { + this(toCopy.scale(), breaker); + zeroBucket(toCopy.zeroBucket()); + sum(toCopy.sum()); + min(toCopy.min()); + max(toCopy.max()); + BucketIterator negBuckets = toCopy.negativeBuckets().iterator(); + while (negBuckets.hasNext()) { + setNegativeBucket(negBuckets.peekIndex(), negBuckets.peekCount()); + negBuckets.advance(); + } + BucketIterator posBuckets = toCopy.positiveBuckets().iterator(); + while (posBuckets.hasNext()) { + setPositiveBucket(posBuckets.peekIndex(), posBuckets.peekCount()); + posBuckets.advance(); + } + } + + public ExponentialHistogramBuilder scale(int scale) { + this.scale = scale; + return this; + } + public ExponentialHistogramBuilder zeroBucket(ZeroBucket zeroBucket) { this.zeroBucket = zeroBucket; return this; @@ -83,39 +106,33 @@ public ExponentialHistogramBuilder max(double max) { } /** - * Adds the given bucket to the positive buckets. - * Buckets may be added in arbitrary order, but each bucket can only be added once. + * Sets the given bucket of the positive buckets. + * Buckets may be set in arbitrary order. If the bucket already exists, it will be replaced. * * @param index the index of the bucket * @param count the count of the bucket, must be at least 1 * @return the builder */ - public ExponentialHistogramBuilder addPositiveBucket(long index, long count) { + public ExponentialHistogramBuilder setPositiveBucket(long index, long count) { if (count < 1) { throw new IllegalArgumentException("Bucket count must be at least 1"); } - if (positiveBuckets.containsKey(index)) { - throw new IllegalArgumentException("Positive bucket already exists: " + index); - } positiveBuckets.put(index, count); return this; } /** - * Adds the given bucket to the negative buckets. - * Buckets may be added in arbitrary order, but each bucket can only be added once. + * Sets the given bucket of the negative buckets. + * Buckets may be set in arbitrary order. If the bucket already exists, it will be replaced. * * @param index the index of the bucket * @param count the count of the bucket, must be at least 1 * @return the builder */ - public ExponentialHistogramBuilder addNegativeBucket(long index, long count) { + public ExponentialHistogramBuilder setNegativeBucket(long index, long count) { if (count < 1) { throw new IllegalArgumentException("Bucket count must be at least 1"); } - if (negativeBuckets.containsKey(index)) { - throw new IllegalArgumentException("Negative bucket already exists: " + index); - } negativeBuckets.put(index, count); return this; } @@ -152,8 +169,6 @@ public ReleasableExponentialHistogram build() { Releasables.close(result); } } - - // Create histogram return result; } } diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramBuilderTests.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramBuilderTests.java index d743a14efe3cc..ddbf3ea20d0e1 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramBuilderTests.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramBuilderTests.java @@ -27,18 +27,18 @@ public class ExponentialHistogramBuilderTests extends ExponentialHistogramTestCase { - public void testBuildWithAllFieldsSet() { + public void testBuildAndCopyWithAllFieldsSet() { ZeroBucket zeroBucket = ZeroBucket.create(1, 2); ExponentialHistogramBuilder builder = ExponentialHistogram.builder(3, breaker()) .zeroBucket(zeroBucket) .sum(100.0) .min(1.0) .max(50.0) - .addPositiveBucket(2, 10) - .addPositiveBucket(0, 1) - .addPositiveBucket(5, 2) - .addNegativeBucket(-2, 5) - .addNegativeBucket(1, 2); + .setPositiveBucket(2, 10) + .setPositiveBucket(0, 1) + .setPositiveBucket(5, 2) + .setNegativeBucket(-2, 5) + .setNegativeBucket(1, 2); try (ReleasableExponentialHistogram histogram = builder.build()) { assertThat(histogram.scale(), equalTo(3)); @@ -48,14 +48,19 @@ public void testBuildWithAllFieldsSet() { assertThat(histogram.max(), equalTo(50.0)); assertBuckets(histogram.positiveBuckets(), List.of(0L, 2L, 5L), List.of(1L, 10L, 2L)); assertBuckets(histogram.negativeBuckets(), List.of(-2L, 1L), List.of(5L, 2L)); + + try (ReleasableExponentialHistogram copy = ExponentialHistogram.builder(histogram, breaker()).build()) { + assertThat(copy, equalTo(histogram)); + } } + } public void testBuildWithEstimation() { ExponentialHistogramBuilder builder = ExponentialHistogram.builder(0, breaker()) - .addPositiveBucket(0, 1) - .addPositiveBucket(1, 1) - .addNegativeBucket(0, 4); + .setPositiveBucket(0, 1) + .setPositiveBucket(1, 1) + .setNegativeBucket(0, 4); try (ReleasableExponentialHistogram histogram = builder.build()) { assertThat(histogram.scale(), equalTo(0)); @@ -68,16 +73,16 @@ public void testBuildWithEstimation() { } } - public void testAddDuplicatePositiveBucketThrows() { + public void testDuplicateBucketOverrides() { ExponentialHistogramBuilder builder = ExponentialHistogram.builder(0, breaker()); - builder.addPositiveBucket(1, 10); - expectThrows(IllegalArgumentException.class, () -> builder.addPositiveBucket(1, 5)); - } - - public void testAddDuplicateNegativeBucketThrows() { - ExponentialHistogramBuilder builder = ExponentialHistogram.builder(0, breaker()); - builder.addNegativeBucket(-1, 10); - expectThrows(IllegalArgumentException.class, () -> builder.addNegativeBucket(-1, 5)); + builder.setPositiveBucket(1, 10); + builder.setNegativeBucket(2, 1); + builder.setPositiveBucket(1, 100); + builder.setNegativeBucket(2, 123); + try (ReleasableExponentialHistogram histogram = builder.build()) { + assertBuckets(histogram.positiveBuckets(), List.of(1L), List.of(100L)); + assertBuckets(histogram.negativeBuckets(), List.of(2L), List.of(123L)); + } } private static void assertBuckets(ExponentialHistogram.Buckets buckets, List indices, List counts) { diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramEqualityTests.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramEqualityTests.java index 3caba373cd2ab..4745262fcb8f1 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramEqualityTests.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramEqualityTests.java @@ -25,7 +25,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import static org.elasticsearch.exponentialhistogram.ExponentialHistogram.MAX_INDEX; @@ -61,7 +60,8 @@ public ExponentialHistogramEqualityTests(Modification modification) { public void testEquality() { ExponentialHistogram histo = randomHistogram(); - ExponentialHistogram copy = copyWithModification(histo, null); + ReleasableExponentialHistogram copy = ExponentialHistogram.builder(histo, breaker()).build(); + autoReleaseOnTestEnd(copy); ExponentialHistogram modifiedCopy = copyWithModification(histo, modification); assertThat(histo, equalTo(copy)); @@ -86,46 +86,31 @@ private ExponentialHistogram randomHistogram() { } private ExponentialHistogram copyWithModification(ExponentialHistogram toCopy, Modification modification) { - int totalBucketCount = getBucketCount(toCopy.positiveBuckets(), toCopy.negativeBuckets()); - FixedCapacityExponentialHistogram copy = createAutoReleasedHistogram(totalBucketCount + 2); - if (modification == Modification.SCALE) { - copy.resetBuckets((int) createRandomLongBetweenOtherThan(MIN_SCALE, MAX_SCALE, toCopy.scale())); - } else { - copy.resetBuckets(toCopy.scale()); - } - if (modification == Modification.SUM) { - copy.setSum(randomDouble()); - } else { - copy.setSum(toCopy.sum()); - } - if (modification == Modification.MIN) { - copy.setMin(randomDouble()); - } else { - copy.setMin(toCopy.min()); + ExponentialHistogramBuilder copyBuilder = ExponentialHistogram.builder(toCopy, breaker()); + switch (modification) { + case SCALE -> copyBuilder.scale((int) createRandomLongBetweenOtherThan(MIN_SCALE, MAX_SCALE, toCopy.scale())); + case SUM -> copyBuilder.sum(randomDouble()); + case MIN -> copyBuilder.min(randomDouble()); + case MAX -> copyBuilder.max(randomDouble()); + case ZERO_THRESHOLD -> copyBuilder.zeroBucket(ZeroBucket.create(randomDouble(), toCopy.zeroBucket().count())); + case ZERO_COUNT -> copyBuilder.zeroBucket( + ZeroBucket.create( + toCopy.zeroBucket().zeroThreshold(), + createRandomLongBetweenOtherThan(0, Long.MAX_VALUE, toCopy.zeroBucket().count()) + ) + ); + case POSITIVE_BUCKETS -> modifyBuckets(copyBuilder, toCopy.positiveBuckets(), true); + case NEGATIVE_BUCKETS -> modifyBuckets(copyBuilder, toCopy.negativeBuckets(), false); } - if (modification == Modification.MAX) { - copy.setMax(randomDouble()); - } else { - copy.setMax(toCopy.max()); - } - long zeroCount = toCopy.zeroBucket().count(); - double zeroThreshold = toCopy.zeroBucket().zeroThreshold(); - if (modification == Modification.ZERO_COUNT) { - zeroCount = createRandomLongBetweenOtherThan(0, Long.MAX_VALUE, zeroCount); - } else if (modification == Modification.ZERO_THRESHOLD) { - zeroThreshold = randomDouble(); - } - copy.setZeroBucket(ZeroBucket.create(zeroThreshold, zeroCount)); - copyBuckets(copy, toCopy.negativeBuckets(), modification == Modification.NEGATIVE_BUCKETS, false); - copyBuckets(copy, toCopy.positiveBuckets(), modification == Modification.POSITIVE_BUCKETS, true); - return copy; + ReleasableExponentialHistogram result = copyBuilder.build(); + autoReleaseOnTestEnd(result); + return result; } - private void copyBuckets( - FixedCapacityExponentialHistogram into, + private ExponentialHistogramBuilder modifyBuckets( + ExponentialHistogramBuilder builder, ExponentialHistogram.Buckets buckets, - boolean modify, boolean isPositive ) { List indices = new ArrayList<>(); @@ -136,29 +121,28 @@ private void copyBuckets( counts.add(it.peekCount()); it.advance(); } - if (modify) { - if (counts.isEmpty() == false && randomBoolean()) { - int toModify = randomIntBetween(0, indices.size() - 1); - counts.set(toModify, createRandomLongBetweenOtherThan(1, Long.MAX_VALUE, counts.get(toModify))); - } else { - insertRandomBucket(indices, counts); - } + long toModifyIndex; + long toModifyCount; + if (counts.isEmpty() == false && randomBoolean()) { + // Modify existing bucket + int position = randomIntBetween(0, indices.size() - 1); + toModifyIndex = indices.get(position); + toModifyCount = createRandomLongBetweenOtherThan(1, Long.MAX_VALUE, counts.get(position)); + } else { + // Add new bucket + long minIndex = indices.stream().mapToLong(Long::longValue).min().orElse(MIN_INDEX); + long maxIndex = indices.stream().mapToLong(Long::longValue).min().orElse(MAX_INDEX); + do { + toModifyIndex = randomLongBetween(Math.max(MIN_INDEX, minIndex - 10), Math.min(MAX_INDEX, maxIndex + 10)); + } while (indices.contains(toModifyIndex)); + toModifyCount = randomLongBetween(1, Long.MAX_VALUE); } - for (int i = 0; i < indices.size(); i++) { - into.tryAddBucket(indices.get(i), counts.get(i), isPositive); + if (isPositive) { + builder.setPositiveBucket(toModifyIndex, toModifyCount); + } else { + builder.setNegativeBucket(toModifyIndex, toModifyCount); } - } - - private void insertRandomBucket(List indices, List counts) { - long minIndex = indices.stream().mapToLong(Long::longValue).min().orElse(MIN_INDEX); - long maxIndex = indices.stream().mapToLong(Long::longValue).min().orElse(MAX_INDEX); - long newIndex; - do { - newIndex = randomLongBetween(Math.max(MIN_INDEX, minIndex - 10), Math.min(MAX_INDEX, maxIndex + 10)); - } while (indices.contains(newIndex)); - int position = -(Collections.binarySearch(indices, newIndex) + 1); - indices.add(position, newIndex); - counts.add(position, randomLongBetween(1, Long.MAX_VALUE)); + return builder; } private static long createRandomLongBetweenOtherThan(long min, long max, long notAllowedValue) { @@ -169,16 +153,4 @@ private static long createRandomLongBetweenOtherThan(long min, long max, long no } while (result == notAllowedValue); return result; } - - private static int getBucketCount(ExponentialHistogram.Buckets... buckets) { - int count = 0; - for (ExponentialHistogram.Buckets val : buckets) { - BucketIterator it = val.iterator(); - while (it.hasNext()) { - count++; - it.advance(); - } - } - return count; - } } diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramMergerTests.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramMergerTests.java index 5e2f8114f5997..0fca2e2dce8c7 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramMergerTests.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramMergerTests.java @@ -43,17 +43,17 @@ public class ExponentialHistogramMergerTests extends ExponentialHistogramTestCas public void testZeroThresholdCollapsesOverlappingBuckets() { - FixedCapacityExponentialHistogram first = createAutoReleasedHistogram(100); - first.setZeroBucket(ZeroBucket.create(2.0001, 10)); - - FixedCapacityExponentialHistogram second = createAutoReleasedHistogram(100); - first.resetBuckets(0); // scale 0 means base 2 - first.tryAddBucket(0, 1, false); // bucket (-2, 1] - first.tryAddBucket(1, 1, false); // bucket (-4, 2] - first.tryAddBucket(2, 7, false); // bucket (-8, 4] - first.tryAddBucket(0, 1, true); // bucket (1, 2] - first.tryAddBucket(1, 1, true); // bucket (2, 4] - first.tryAddBucket(2, 42, true); // bucket (4, 8] + ExponentialHistogram first = createAutoReleasedHistogram(b -> b.zeroBucket(ZeroBucket.create(2.0001, 10))); + + ExponentialHistogram second = createAutoReleasedHistogram( + b -> b.scale(0) + .setNegativeBucket(0, 1) + .setNegativeBucket(1, 1) + .setNegativeBucket(2, 7) + .setPositiveBucket(0, 1) + .setPositiveBucket(1, 1) + .setPositiveBucket(2, 42) + ); ExponentialHistogram mergeResult = mergeWithMinimumScale(100, 0, first, second); @@ -76,8 +76,7 @@ public void testZeroThresholdCollapsesOverlappingBuckets() { assertThat(posBuckets.hasNext(), equalTo(false)); // ensure buckets of the accumulated histogram are collapsed too if needed - FixedCapacityExponentialHistogram third = createAutoReleasedHistogram(100); - third.setZeroBucket(ZeroBucket.create(45.0, 1)); + ExponentialHistogram third = createAutoReleasedHistogram(b -> b.zeroBucket(ZeroBucket.create(45.0, 1))); mergeResult = mergeWithMinimumScale(100, 0, mergeResult, third); assertThat(mergeResult.zeroBucket().zeroThreshold(), closeTo(45.0, 0.000001)); @@ -87,14 +86,11 @@ public void testZeroThresholdCollapsesOverlappingBuckets() { } public void testEmptyZeroBucketIgnored() { - FixedCapacityExponentialHistogram first = createAutoReleasedHistogram(100); - first.setZeroBucket(ZeroBucket.create(2.0, 10)); - first.resetBuckets(0); // scale 0 means base 2 - first.tryAddBucket(2, 42L, true); // bucket (4, 8] - - FixedCapacityExponentialHistogram second = createAutoReleasedHistogram(100); - second.setZeroBucket(ZeroBucket.create(100.0, 0)); + ExponentialHistogram first = createAutoReleasedHistogram( + b -> b.zeroBucket(ZeroBucket.create(2.0, 10)).scale(0).setPositiveBucket(2, 42) + ); + ExponentialHistogram second = createAutoReleasedHistogram(b -> b.zeroBucket(ZeroBucket.create(100.0, 0))); ExponentialHistogram mergeResult = mergeWithMinimumScale(100, 0, first, second); assertThat(mergeResult.zeroBucket().zeroThreshold(), equalTo(2.0)); @@ -136,12 +132,15 @@ public void testUpscalingDoesNotExceedIndexLimits() { boolean isPositive = i % 2 == 0; boolean useMinIndex = i > 1; - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(2); - histo.resetBuckets(20); - long index = useMinIndex ? MIN_INDEX / 2 : MAX_INDEX / 2; - - histo.tryAddBucket(index, 1, isPositive); + ExponentialHistogram histo = createAutoReleasedHistogram(b -> { + b.scale(20); + if (isPositive) { + b.setPositiveBucket(index, 1); + } else { + b.setNegativeBucket(index, 1); + } + }); try (ReleasableExponentialHistogram result = ExponentialHistogram.merge(100, breaker(), histo)) { assertThat(result.scale(), equalTo(21)); diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramTestCase.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramTestCase.java index c13c4d2608295..174646dfb4582 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramTestCase.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramTestCase.java @@ -28,13 +28,14 @@ import org.junit.After; import java.util.ArrayList; +import java.util.function.Consumer; public abstract class ExponentialHistogramTestCase extends ESTestCase { private final ArrayList releaseBeforeEnd = new ArrayList<>(); /** - * Release all histograms created via {@link #createAutoReleasedHistogram(int)} + * Release all histograms registered via {@link #autoReleaseOnTestEnd(ReleasableExponentialHistogram)} * before {@link ESTestCase} checks for unreleased bytes. */ @After @@ -61,8 +62,10 @@ void autoReleaseOnTestEnd(ReleasableExponentialHistogram toRelease) { releaseBeforeEnd.add(toRelease); } - FixedCapacityExponentialHistogram createAutoReleasedHistogram(int numBuckets) { - FixedCapacityExponentialHistogram result = FixedCapacityExponentialHistogram.create(numBuckets, breaker()); + ExponentialHistogram createAutoReleasedHistogram(Consumer customizer) { + ExponentialHistogramBuilder resultBuilder = ExponentialHistogram.builder(ExponentialHistogram.MAX_SCALE, breaker()); + customizer.accept(resultBuilder); + ReleasableExponentialHistogram result = resultBuilder.build(); releaseBeforeEnd.add(result); return result; } diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramUtilsTests.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramUtilsTests.java index 59909f21333fb..60dc7908a08db 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramUtilsTests.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramUtilsTests.java @@ -60,24 +60,18 @@ public void testRandomDataSumEstimation() { } public void testSumInfinityHandling() { - FixedCapacityExponentialHistogram morePositiveValues = createAutoReleasedHistogram(100); - morePositiveValues.resetBuckets(0); - morePositiveValues.tryAddBucket(1999, 1, false); - morePositiveValues.tryAddBucket(2000, 2, false); - morePositiveValues.tryAddBucket(1999, 2, true); - morePositiveValues.tryAddBucket(2000, 2, true); + ExponentialHistogram morePositiveValues = createAutoReleasedHistogram( + b -> b.scale(0).setNegativeBucket(1999, 1).setNegativeBucket(2000, 2).setPositiveBucket(1999, 2).setPositiveBucket(2000, 2) + ); double sum = ExponentialHistogramUtils.estimateSum( morePositiveValues.negativeBuckets().iterator(), morePositiveValues.positiveBuckets().iterator() ); assertThat(sum, equalTo(Double.POSITIVE_INFINITY)); - FixedCapacityExponentialHistogram moreNegativeValues = createAutoReleasedHistogram(100); - moreNegativeValues.resetBuckets(0); - moreNegativeValues.tryAddBucket(1999, 2, false); - moreNegativeValues.tryAddBucket(2000, 2, false); - moreNegativeValues.tryAddBucket(1999, 1, true); - moreNegativeValues.tryAddBucket(2000, 2, true); + ExponentialHistogram moreNegativeValues = createAutoReleasedHistogram( + b -> b.scale(0).setNegativeBucket(1999, 2).setNegativeBucket(2000, 2).setPositiveBucket(1999, 1).setPositiveBucket(2000, 2) + ); sum = ExponentialHistogramUtils.estimateSum( moreNegativeValues.negativeBuckets().iterator(), @@ -143,9 +137,7 @@ public void testMinMaxEstimation() { } public void testMinMaxEstimationPositiveInfinityHandling() { - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(100); - histo.resetBuckets(0); - histo.tryAddBucket(2000, 1, true); + ExponentialHistogram histo = createAutoReleasedHistogram(b -> b.scale(0).setPositiveBucket(2000, 1)); OptionalDouble minEstimate = ExponentialHistogramUtils.estimateMin( ZeroBucket.minimalEmpty(), @@ -165,9 +157,7 @@ public void testMinMaxEstimationPositiveInfinityHandling() { } public void testMinMaxEstimationNegativeInfinityHandling() { - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(100); - histo.resetBuckets(0); - histo.tryAddBucket(2000, 1, false); + ExponentialHistogram histo = createAutoReleasedHistogram(b -> b.scale(0).setNegativeBucket(2000, 1)); OptionalDouble minEstimate = ExponentialHistogramUtils.estimateMin( ZeroBucket.minimalEmpty(), diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramXContentTests.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramXContentTests.java index 7ef623ac395d2..495e68031851c 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramXContentTests.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ExponentialHistogramXContentTests.java @@ -37,16 +37,17 @@ public void testEmptyHistogram() { } public void testFullHistogram() { - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(100); - histo.setZeroBucket(ZeroBucket.create(0.1234, 42)); - histo.resetBuckets(7); - histo.setSum(1234.56); - histo.setMin(-321.123); - histo.setMax(123.123); - histo.tryAddBucket(-10, 15, false); - histo.tryAddBucket(10, 5, false); - histo.tryAddBucket(-11, 10, true); - histo.tryAddBucket(11, 20, true); + ExponentialHistogram histo = createAutoReleasedHistogram( + b -> b.zeroBucket(ZeroBucket.create(0.1234, 42)) + .scale(7) + .sum(1234.56) + .min(-321.123) + .max(123.123) + .setNegativeBucket(-10, 15) + .setNegativeBucket(10, 5) + .setPositiveBucket(-11, 10) + .setPositiveBucket(11, 20) + ); assertThat( toJson(histo), equalTo( @@ -64,31 +65,21 @@ public void testFullHistogram() { } public void testOnlyZeroThreshold() { - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(10); - histo.setZeroBucket(ZeroBucket.create(5.0, 0)); - histo.resetBuckets(3); - histo.setSum(1.1); + ExponentialHistogram histo = createAutoReleasedHistogram(b -> b.scale(3).sum(1.1).zeroBucket(ZeroBucket.create(5.0, 0))); assertThat(toJson(histo), equalTo("{\"scale\":3,\"sum\":1.1,\"zero\":{\"threshold\":5.0}}")); } public void testOnlyZeroCount() { - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(10); - histo.setZeroBucket(ZeroBucket.create(0.0, 7)); - histo.resetBuckets(2); - histo.setSum(1.1); - histo.setMin(0); - histo.setMax(0); + ExponentialHistogram histo = createAutoReleasedHistogram( + b -> b.zeroBucket(ZeroBucket.create(0.0, 7)).scale(2).sum(1.1).min(0).max(0) + ); assertThat(toJson(histo), equalTo("{\"scale\":2,\"sum\":1.1,\"min\":0.0,\"max\":0.0,\"zero\":{\"count\":7}}")); } public void testOnlyPositiveBuckets() { - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(10); - histo.resetBuckets(4); - histo.setSum(1.1); - histo.setMin(0.5); - histo.setMax(2.5); - histo.tryAddBucket(-1, 3, true); - histo.tryAddBucket(2, 5, true); + ExponentialHistogram histo = createAutoReleasedHistogram( + b -> b.scale(4).sum(1.1).min(0.5).max(2.5).setPositiveBucket(-1, 3).setPositiveBucket(2, 5) + ); assertThat( toJson(histo), equalTo("{\"scale\":4,\"sum\":1.1,\"min\":0.5,\"max\":2.5,\"positive\":{\"indices\":[-1,2],\"counts\":[3,5]}}") @@ -96,13 +87,9 @@ public void testOnlyPositiveBuckets() { } public void testOnlyNegativeBuckets() { - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(10); - histo.resetBuckets(5); - histo.setSum(1.1); - histo.setMin(-0.5); - histo.setMax(-0.25); - histo.tryAddBucket(-1, 4, false); - histo.tryAddBucket(2, 6, false); + ExponentialHistogram histo = createAutoReleasedHistogram( + b -> b.scale(5).sum(1.1).min(-0.5).max(-0.25).setNegativeBucket(-1, 4).setNegativeBucket(2, 6) + ); assertThat( toJson(histo), equalTo("{\"scale\":5,\"sum\":1.1,\"min\":-0.5,\"max\":-0.25,\"negative\":{\"indices\":[-1,2],\"counts\":[4,6]}}") diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/FixedCapacityExponentialHistogramTests.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/FixedCapacityExponentialHistogramTests.java index 7f98c3e2d4e74..c351a51d7f40a 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/FixedCapacityExponentialHistogramTests.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/FixedCapacityExponentialHistogramTests.java @@ -31,7 +31,8 @@ public class FixedCapacityExponentialHistogramTests extends ExponentialHistogram public void testValueCountUpdatedCorrectly() { - FixedCapacityExponentialHistogram histogram = createAutoReleasedHistogram(100); + FixedCapacityExponentialHistogram histogram = FixedCapacityExponentialHistogram.create(100, breaker()); + autoReleaseOnTestEnd(histogram); assertThat(histogram.negativeBuckets().valueCount(), equalTo(0L)); assertThat(histogram.positiveBuckets().valueCount(), equalTo(0L)); diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/QuantileAccuracyTests.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/QuantileAccuracyTests.java index cec0d1f0f0ff7..b5fa234ac7cb0 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/QuantileAccuracyTests.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/QuantileAccuracyTests.java @@ -56,10 +56,9 @@ private static int randomBucketCount() { } public void testNoNegativeZeroReturned() { - FixedCapacityExponentialHistogram histogram = createAutoReleasedHistogram(2); - histogram.resetBuckets(MAX_SCALE); - // add a single, negative bucket close to zero - histogram.tryAddBucket(MIN_INDEX, 3, false); + ExponentialHistogram histogram = createAutoReleasedHistogram( + b -> b.scale(MAX_SCALE).setNegativeBucket(MIN_INDEX, 3) // add a single, negative bucket close to zero + ); double median = ExponentialHistogramQuantile.getQuantile(histogram, 0.5); assertThat(median, equalTo(0.0)); } diff --git a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ZeroBucketTests.java b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ZeroBucketTests.java index 2ed25afb31107..ae5659da1d20b 100644 --- a/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ZeroBucketTests.java +++ b/libs/exponential-histogram/src/test/java/org/elasticsearch/exponentialhistogram/ZeroBucketTests.java @@ -44,9 +44,9 @@ public void testMergingPreservesExactThreshold() { } public void testBucketCollapsingPreservesExactThreshold() { - FixedCapacityExponentialHistogram histo = createAutoReleasedHistogram(2); - histo.resetBuckets(0); - histo.tryAddBucket(0, 42, true); // bucket [1,2] + ExponentialHistogram histo = createAutoReleasedHistogram( + b -> b.scale(0).setPositiveBucket(0, 42) // bucket [1,2] + ); ZeroBucket bucketA = ZeroBucket.create(3.0, 10);