From 9e89f74bc57d0e7df289eea31d8272d14b772953 Mon Sep 17 00:00:00 2001 From: ChrisHegarty Date: Mon, 2 Oct 2023 12:40:58 +0100 Subject: [PATCH] Fix accountancy in block and vector builders --- .../compute/data/BooleanBlockBuilder.java | 15 +-- .../compute/data/BooleanVectorBuilder.java | 13 +- .../data/BooleanVectorFixedBuilder.java | 10 +- .../compute/data/DoubleBlockBuilder.java | 15 +-- .../compute/data/DoubleVectorBuilder.java | 13 +- .../data/DoubleVectorFixedBuilder.java | 10 +- .../compute/data/IntBlockBuilder.java | 15 +-- .../compute/data/IntVectorBuilder.java | 13 +- .../compute/data/IntVectorFixedBuilder.java | 10 +- .../compute/data/LongBlockBuilder.java | 15 +-- .../compute/data/LongVectorBuilder.java | 13 +- .../compute/data/LongVectorFixedBuilder.java | 10 +- .../compute/data/BlockFactory.java | 113 ++++++++++-------- .../compute/data/X-BlockBuilder.java.st | 15 +-- .../compute/data/X-VectorBuilder.java.st | 13 +- .../compute/data/X-VectorFixedBuilder.java.st | 10 +- .../compute/data/BlockBuilderTests.java | 71 +++++++---- .../compute/data/VectorBuilderTests.java | 24 ++-- .../compute/data/VectorFixedBuilderTests.java | 24 ++-- 19 files changed, 193 insertions(+), 229 deletions(-) diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanBlockBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanBlockBuilder.java index 98b9fdb948bc..b52d8cf19b3d 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanBlockBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanBlockBuilder.java @@ -183,26 +183,17 @@ public BooleanBlock build() { finish(); BooleanBlock block; if (hasNonNullValue && positionCount == 1 && valueCount == 1) { - block = new ConstantBooleanVector(values[0], 1, blockFactory).asBlock(); + block = blockFactory.newConstantBooleanBlockWith(values[0], 1, estimatedBytes); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } if (isDense() && singleValued()) { - block = new BooleanArrayVector(values, positionCount, blockFactory).asBlock(); + block = blockFactory.newBooleanArrayVector(values, positionCount, estimatedBytes).asBlock(); } else { - block = new BooleanArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, blockFactory); + block = blockFactory.newBooleanArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, estimatedBytes); } } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(block.ramBytesUsed() - estimatedBytes, false); built(); return block; } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanVectorBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanVectorBuilder.java index 3792e39275f8..effb90267702 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanVectorBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanVectorBuilder.java @@ -52,22 +52,13 @@ public BooleanVector build() { finish(); BooleanVector vector; if (valueCount == 1) { - vector = new ConstantBooleanVector(values[0], 1, blockFactory); + vector = blockFactory.newConstantBooleanBlockWith(values[0], 1, estimatedBytes).asVector(); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } - vector = new BooleanArrayVector(values, valueCount, blockFactory); + vector = blockFactory.newBooleanArrayVector(values, valueCount, estimatedBytes); } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(vector.ramBytesUsed() - estimatedBytes, false); built(); return vector; } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanVectorFixedBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanVectorFixedBuilder.java index 1428a1a221fa..9a07816666ef 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanVectorFixedBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/BooleanVectorFixedBuilder.java @@ -18,6 +18,7 @@ final class BooleanVectorFixedBuilder implements BooleanVector.FixedBuilder { private final BlockFactory blockFactory; private final boolean[] values; + private final long preAdjustedBytes; /** * The next value to write into. {@code -1} means the vector has already * been built. @@ -25,7 +26,8 @@ final class BooleanVectorFixedBuilder implements BooleanVector.FixedBuilder { private int nextIndex; BooleanVectorFixedBuilder(int size, BlockFactory blockFactory) { - blockFactory.adjustBreaker(ramBytesUsed(size), false); + preAdjustedBytes = ramBytesUsed(size); + blockFactory.adjustBreaker(preAdjustedBytes, false); this.blockFactory = blockFactory; this.values = new boolean[size]; } @@ -54,16 +56,16 @@ public BooleanVector build() { } nextIndex = -1; if (values.length == 1) { - return new ConstantBooleanVector(values[0], 1, blockFactory); + return blockFactory.newConstantBooleanBlockWith(values[0], 1, preAdjustedBytes).asVector(); } - return new BooleanArrayVector(values, values.length, blockFactory); + return blockFactory.newBooleanArrayVector(values, values.length, preAdjustedBytes); } @Override public void close() { if (nextIndex >= 0) { // If nextIndex < 0 we've already built the vector - blockFactory.adjustBreaker(-ramBytesUsed(values.length), false); + blockFactory.adjustBreaker(-preAdjustedBytes, false); } } } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleBlockBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleBlockBuilder.java index dca8fe2d0d2e..0267f07f20c7 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleBlockBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleBlockBuilder.java @@ -183,26 +183,17 @@ public DoubleBlock build() { finish(); DoubleBlock block; if (hasNonNullValue && positionCount == 1 && valueCount == 1) { - block = new ConstantDoubleVector(values[0], 1, blockFactory).asBlock(); + block = blockFactory.newConstantDoubleBlockWith(values[0], 1, estimatedBytes); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } if (isDense() && singleValued()) { - block = new DoubleArrayVector(values, positionCount, blockFactory).asBlock(); + block = blockFactory.newDoubleArrayVector(values, positionCount, estimatedBytes).asBlock(); } else { - block = new DoubleArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, blockFactory); + block = blockFactory.newDoubleArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, estimatedBytes); } } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(block.ramBytesUsed() - estimatedBytes, false); built(); return block; } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleVectorBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleVectorBuilder.java index 12fa06a944fb..f4e7be406e1c 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleVectorBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleVectorBuilder.java @@ -52,22 +52,13 @@ public DoubleVector build() { finish(); DoubleVector vector; if (valueCount == 1) { - vector = new ConstantDoubleVector(values[0], 1, blockFactory); + vector = blockFactory.newConstantDoubleBlockWith(values[0], 1, estimatedBytes).asVector(); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } - vector = new DoubleArrayVector(values, valueCount, blockFactory); + vector = blockFactory.newDoubleArrayVector(values, valueCount, estimatedBytes); } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(vector.ramBytesUsed() - estimatedBytes, false); built(); return vector; } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleVectorFixedBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleVectorFixedBuilder.java index b636d9eb1975..57a423985b0c 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleVectorFixedBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/DoubleVectorFixedBuilder.java @@ -18,6 +18,7 @@ final class DoubleVectorFixedBuilder implements DoubleVector.FixedBuilder { private final BlockFactory blockFactory; private final double[] values; + private final long preAdjustedBytes; /** * The next value to write into. {@code -1} means the vector has already * been built. @@ -25,7 +26,8 @@ final class DoubleVectorFixedBuilder implements DoubleVector.FixedBuilder { private int nextIndex; DoubleVectorFixedBuilder(int size, BlockFactory blockFactory) { - blockFactory.adjustBreaker(ramBytesUsed(size), false); + preAdjustedBytes = ramBytesUsed(size); + blockFactory.adjustBreaker(preAdjustedBytes, false); this.blockFactory = blockFactory; this.values = new double[size]; } @@ -54,16 +56,16 @@ public DoubleVector build() { } nextIndex = -1; if (values.length == 1) { - return new ConstantDoubleVector(values[0], 1, blockFactory); + return blockFactory.newConstantDoubleBlockWith(values[0], 1, preAdjustedBytes).asVector(); } - return new DoubleArrayVector(values, values.length, blockFactory); + return blockFactory.newDoubleArrayVector(values, values.length, preAdjustedBytes); } @Override public void close() { if (nextIndex >= 0) { // If nextIndex < 0 we've already built the vector - blockFactory.adjustBreaker(-ramBytesUsed(values.length), false); + blockFactory.adjustBreaker(-preAdjustedBytes, false); } } } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntBlockBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntBlockBuilder.java index ba96f85e7319..98fce58fbfbf 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntBlockBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntBlockBuilder.java @@ -183,26 +183,17 @@ public IntBlock build() { finish(); IntBlock block; if (hasNonNullValue && positionCount == 1 && valueCount == 1) { - block = new ConstantIntVector(values[0], 1, blockFactory).asBlock(); + block = blockFactory.newConstantIntBlockWith(values[0], 1, estimatedBytes); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } if (isDense() && singleValued()) { - block = new IntArrayVector(values, positionCount, blockFactory).asBlock(); + block = blockFactory.newIntArrayVector(values, positionCount, estimatedBytes).asBlock(); } else { - block = new IntArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, blockFactory); + block = blockFactory.newIntArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, estimatedBytes); } } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(block.ramBytesUsed() - estimatedBytes, false); built(); return block; } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntVectorBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntVectorBuilder.java index 155adfec02b9..09bbb32cefe7 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntVectorBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntVectorBuilder.java @@ -52,22 +52,13 @@ public IntVector build() { finish(); IntVector vector; if (valueCount == 1) { - vector = new ConstantIntVector(values[0], 1, blockFactory); + vector = blockFactory.newConstantIntBlockWith(values[0], 1, estimatedBytes).asVector(); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } - vector = new IntArrayVector(values, valueCount, blockFactory); + vector = blockFactory.newIntArrayVector(values, valueCount, estimatedBytes); } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(vector.ramBytesUsed() - estimatedBytes, false); built(); return vector; } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntVectorFixedBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntVectorFixedBuilder.java index 03a15fb10a80..98565a6b94d4 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntVectorFixedBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/IntVectorFixedBuilder.java @@ -18,6 +18,7 @@ final class IntVectorFixedBuilder implements IntVector.FixedBuilder { private final BlockFactory blockFactory; private final int[] values; + private final long preAdjustedBytes; /** * The next value to write into. {@code -1} means the vector has already * been built. @@ -25,7 +26,8 @@ final class IntVectorFixedBuilder implements IntVector.FixedBuilder { private int nextIndex; IntVectorFixedBuilder(int size, BlockFactory blockFactory) { - blockFactory.adjustBreaker(ramBytesUsed(size), false); + preAdjustedBytes = ramBytesUsed(size); + blockFactory.adjustBreaker(preAdjustedBytes, false); this.blockFactory = blockFactory; this.values = new int[size]; } @@ -54,16 +56,16 @@ public IntVector build() { } nextIndex = -1; if (values.length == 1) { - return new ConstantIntVector(values[0], 1, blockFactory); + return blockFactory.newConstantIntBlockWith(values[0], 1, preAdjustedBytes).asVector(); } - return new IntArrayVector(values, values.length, blockFactory); + return blockFactory.newIntArrayVector(values, values.length, preAdjustedBytes); } @Override public void close() { if (nextIndex >= 0) { // If nextIndex < 0 we've already built the vector - blockFactory.adjustBreaker(-ramBytesUsed(values.length), false); + blockFactory.adjustBreaker(-preAdjustedBytes, false); } } } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongBlockBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongBlockBuilder.java index 09d858e7c9b0..f2eff13562e1 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongBlockBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongBlockBuilder.java @@ -183,26 +183,17 @@ public LongBlock build() { finish(); LongBlock block; if (hasNonNullValue && positionCount == 1 && valueCount == 1) { - block = new ConstantLongVector(values[0], 1, blockFactory).asBlock(); + block = blockFactory.newConstantLongBlockWith(values[0], 1, estimatedBytes); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } if (isDense() && singleValued()) { - block = new LongArrayVector(values, positionCount, blockFactory).asBlock(); + block = blockFactory.newLongArrayVector(values, positionCount, estimatedBytes).asBlock(); } else { - block = new LongArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, blockFactory); + block = blockFactory.newLongArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, estimatedBytes); } } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(block.ramBytesUsed() - estimatedBytes, false); built(); return block; } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongVectorBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongVectorBuilder.java index 3b8bbf4219d0..eb4e54781a02 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongVectorBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongVectorBuilder.java @@ -52,22 +52,13 @@ public LongVector build() { finish(); LongVector vector; if (valueCount == 1) { - vector = new ConstantLongVector(values[0], 1, blockFactory); + vector = blockFactory.newConstantLongBlockWith(values[0], 1, estimatedBytes).asVector(); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } - vector = new LongArrayVector(values, valueCount, blockFactory); + vector = blockFactory.newLongArrayVector(values, valueCount, estimatedBytes); } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(vector.ramBytesUsed() - estimatedBytes, false); built(); return vector; } diff --git a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongVectorFixedBuilder.java b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongVectorFixedBuilder.java index 0960d607d9c0..0849cbc76084 100644 --- a/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongVectorFixedBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/generated-src/org/elasticsearch/compute/data/LongVectorFixedBuilder.java @@ -18,6 +18,7 @@ final class LongVectorFixedBuilder implements LongVector.FixedBuilder { private final BlockFactory blockFactory; private final long[] values; + private final long preAdjustedBytes; /** * The next value to write into. {@code -1} means the vector has already * been built. @@ -25,7 +26,8 @@ final class LongVectorFixedBuilder implements LongVector.FixedBuilder { private int nextIndex; LongVectorFixedBuilder(int size, BlockFactory blockFactory) { - blockFactory.adjustBreaker(ramBytesUsed(size), false); + preAdjustedBytes = ramBytesUsed(size); + blockFactory.adjustBreaker(preAdjustedBytes, false); this.blockFactory = blockFactory; this.values = new long[size]; } @@ -54,16 +56,16 @@ public LongVector build() { } nextIndex = -1; if (values.length == 1) { - return new ConstantLongVector(values[0], 1, blockFactory); + return blockFactory.newConstantLongBlockWith(values[0], 1, preAdjustedBytes).asVector(); } - return new LongArrayVector(values, values.length, blockFactory); + return blockFactory.newLongArrayVector(values, values.length, preAdjustedBytes); } @Override public void close() { if (nextIndex >= 0) { // If nextIndex < 0 we've already built the vector - blockFactory.adjustBreaker(-ramBytesUsed(values.length), false); + blockFactory.adjustBreaker(-preAdjustedBytes, false); } } } diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockFactory.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockFactory.java index 780155f8a840..0bb49d205669 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockFactory.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockFactory.java @@ -67,11 +67,11 @@ void adjustBreaker(final long delta, final boolean isDataAlreadyCreated) { try { breaker.addEstimateBytesAndMaybeBreak(delta, ""); } catch (CircuitBreakingException e) { - if (isDataAlreadyCreated) { - // since we've already created the data, we need to - // add it so closing the stream re-adjusts properly - breaker.addWithoutBreaking(delta); - } + // if (isDataAlreadyCreated) { // TODO: remove isDataAlreadyCreated + // since we've already created the data, we need to + // add it so closing the stream re-adjusts properly + // breaker.addWithoutBreaking(delta); + // } // re-throw the original exception throw e; } @@ -113,15 +113,13 @@ BooleanVector.FixedBuilder newBooleanVectorFixedBuilder(int size) { return new BooleanVectorFixedBuilder(size, this); } - public BooleanBlock newBooleanArrayBlock( - boolean[] values, - int positionCount, - int[] firstValueIndexes, - BitSet nulls, - MvOrdering mvOrdering - ) { - var b = new BooleanArrayBlock(values, positionCount, firstValueIndexes, nulls, mvOrdering, this); - adjustBreaker(b.ramBytesUsed(), true); + public final BooleanBlock newBooleanArrayBlock(boolean[] values, int pc, int[] firstValueIndexes, BitSet nulls, MvOrdering mvOrdering) { + return newBooleanArrayBlock(values, pc, firstValueIndexes, nulls, mvOrdering, 0L); + } + + public BooleanBlock newBooleanArrayBlock(boolean[] values, int pc, int[] fvi, BitSet nulls, MvOrdering mvOrder, long preAdjustedBytes) { + var b = new BooleanArrayBlock(values, pc, fvi, nulls, mvOrder, this); + adjustBreaker(b.ramBytesUsed() - preAdjustedBytes, true); return b; } @@ -129,7 +127,7 @@ public BooleanVector.Builder newBooleanVectorBuilder(int estimatedSize) { return new BooleanVectorBuilder(estimatedSize, this); } - public BooleanVector newBooleanArrayVector(boolean[] values, int positionCount) { + public final BooleanVector newBooleanArrayVector(boolean[] values, int positionCount) { return newBooleanArrayVector(values, positionCount, 0L); } @@ -139,9 +137,13 @@ public BooleanVector newBooleanArrayVector(boolean[] values, int positionCount, return b; } - public BooleanBlock newConstantBooleanBlockWith(boolean value, int positions) { + public final BooleanBlock newConstantBooleanBlockWith(boolean value, int positions) { + return newConstantBooleanBlockWith(value, positions, 0L); + } + + public BooleanBlock newConstantBooleanBlockWith(boolean value, int positions, long preAdjustedBytes) { var b = new ConstantBooleanVector(value, positions, this).asBlock(); - adjustBreaker(b.ramBytesUsed(), true); + adjustBreaker(b.ramBytesUsed() - preAdjustedBytes, true); return b; } @@ -149,9 +151,13 @@ public IntBlock.Builder newIntBlockBuilder(int estimatedSize) { return new IntBlockBuilder(estimatedSize, this); } - public IntBlock newIntArrayBlock(int[] values, int positionCount, int[] firstValueIndexes, BitSet nulls, MvOrdering mvOrdering) { - var b = new IntArrayBlock(values, positionCount, firstValueIndexes, nulls, mvOrdering, this); - adjustBreaker(b.ramBytesUsed(), true); + public final IntBlock newIntArrayBlock(int[] values, int positionCount, int[] firstValueIndexes, BitSet nulls, MvOrdering mvOrdering) { + return newIntArrayBlock(values, positionCount, firstValueIndexes, nulls, mvOrdering, 0L); + } + + public IntBlock newIntArrayBlock(int[] values, int pc, int[] fvi, BitSet nulls, MvOrdering mvOrdering, long preAdjustedBytes) { + var b = new IntArrayBlock(values, pc, fvi, nulls, mvOrdering, this); + adjustBreaker(b.ramBytesUsed() - preAdjustedBytes, true); return b; } @@ -167,7 +173,7 @@ IntVector.FixedBuilder newIntVectorFixedBuilder(int size) { * Creates a new Vector with the given values and positionCount. Equivalent to: * newIntArrayVector(values, positionCount, 0L); // with zero pre-adjusted bytes */ - public IntVector newIntArrayVector(int[] values, int positionCount) { + public final IntVector newIntArrayVector(int[] values, int positionCount) { return newIntArrayVector(values, positionCount, 0L); } @@ -188,9 +194,13 @@ public IntVector newIntArrayVector(int[] values, int positionCount, long preAdju return b; } - public IntBlock newConstantIntBlockWith(int value, int positions) { + public final IntBlock newConstantIntBlockWith(int value, int positions) { + return newConstantIntBlockWith(value, positions, 0L); + } + + public IntBlock newConstantIntBlockWith(int value, int positions, long preAdjustedBytes) { var b = new ConstantIntVector(value, positions, this).asBlock(); - adjustBreaker(b.ramBytesUsed(), true); + adjustBreaker(b.ramBytesUsed() - preAdjustedBytes, true); return b; } @@ -198,9 +208,13 @@ public LongBlock.Builder newLongBlockBuilder(int estimatedSize) { return new LongBlockBuilder(estimatedSize, this); } - public LongBlock newLongArrayBlock(long[] values, int positionCount, int[] firstValueIndexes, BitSet nulls, MvOrdering mvOrdering) { - var b = new LongArrayBlock(values, positionCount, firstValueIndexes, nulls, mvOrdering, this); - adjustBreaker(b.ramBytesUsed(), true); + public final LongBlock newLongArrayBlock(long[] values, int pc, int[] firstValueIndexes, BitSet nulls, MvOrdering mvOrdering) { + return newLongArrayBlock(values, pc, firstValueIndexes, nulls, mvOrdering, 0L); + } + + public LongBlock newLongArrayBlock(long[] values, int pc, int[] fvi, BitSet nulls, MvOrdering mvOrdering, long preAdjustedBytes) { + var b = new LongArrayBlock(values, pc, fvi, nulls, mvOrdering, this); + adjustBreaker(b.ramBytesUsed() - preAdjustedBytes, true); return b; } @@ -212,7 +226,7 @@ LongVector.FixedBuilder newLongVectorFixedBuilder(int size) { return new LongVectorFixedBuilder(size, this); } - public LongVector newLongArrayVector(long[] values, int positionCount) { + public final LongVector newLongArrayVector(long[] values, int positionCount) { return newLongArrayVector(values, positionCount, 0L); } @@ -222,9 +236,13 @@ public LongVector newLongArrayVector(long[] values, int positionCount, long preA return b; } - public LongBlock newConstantLongBlockWith(long value, int positions) { + public final LongBlock newConstantLongBlockWith(long value, int positions) { + return newConstantLongBlockWith(value, positions, 0L); + } + + public LongBlock newConstantLongBlockWith(long value, int positions, long preAdjustedBytes) { var b = new ConstantLongVector(value, positions, this).asBlock(); - adjustBreaker(b.ramBytesUsed(), true); + adjustBreaker(b.ramBytesUsed() - preAdjustedBytes, true); return b; } @@ -232,15 +250,14 @@ public DoubleBlock.Builder newDoubleBlockBuilder(int estimatedSize) { return new DoubleBlockBuilder(estimatedSize, this); } - public DoubleBlock newDoubleArrayBlock( - double[] values, - int positionCount, - int[] firstValueIndexes, - BitSet nulls, - MvOrdering mvOrdering - ) { - var b = new DoubleArrayBlock(values, positionCount, firstValueIndexes, nulls, mvOrdering, this); - adjustBreaker(b.ramBytesUsed(), true); + public final DoubleBlock newDoubleArrayBlock(double[] values, int pc, int[] firstValueIndexes, BitSet nulls, MvOrdering mvOrdering) { + return newDoubleArrayBlock(values, pc, firstValueIndexes, nulls, mvOrdering, 0L); + + } + + public DoubleBlock newDoubleArrayBlock(double[] values, int pc, int[] fvi, BitSet nulls, MvOrdering mvOrdering, long preAdjustedBytes) { + var b = new DoubleArrayBlock(values, pc, fvi, nulls, mvOrdering, this); + adjustBreaker(b.ramBytesUsed() - preAdjustedBytes, true); return b; } @@ -252,7 +269,7 @@ DoubleVector.FixedBuilder newDoubleVectorFixedBuilder(int size) { return new DoubleVectorFixedBuilder(size, this); } - public DoubleVector newDoubleArrayVector(double[] values, int positionCount) { + public final DoubleVector newDoubleArrayVector(double[] values, int positionCount) { return newDoubleArrayVector(values, positionCount, 0L); } @@ -262,9 +279,13 @@ public DoubleVector newDoubleArrayVector(double[] values, int positionCount, lon return b; } - public DoubleBlock newConstantDoubleBlockWith(double value, int positions) { + public final DoubleBlock newConstantDoubleBlockWith(double value, int positions) { + return newConstantDoubleBlockWith(value, positions, 0L); + } + + public DoubleBlock newConstantDoubleBlockWith(double value, int positions, long preAdjustedBytes) { var b = new ConstantDoubleVector(value, positions, this).asBlock(); - adjustBreaker(b.ramBytesUsed(), true); + adjustBreaker(b.ramBytesUsed() - preAdjustedBytes, true); return b; } @@ -272,14 +293,8 @@ public BytesRefBlock.Builder newBytesRefBlockBuilder(int estimatedSize) { return new BytesRefBlockBuilder(estimatedSize, bigArrays, this); } - public BytesRefBlock newBytesRefArrayBlock( - BytesRefArray values, - int positionCount, - int[] firstValueIndexes, - BitSet nulls, - MvOrdering mvOrdering - ) { - var b = new BytesRefArrayBlock(values, positionCount, firstValueIndexes, nulls, mvOrdering, this); + public BytesRefBlock newBytesRefArrayBlock(BytesRefArray values, int pc, int[] firstValueIndexes, BitSet nulls, MvOrdering mvOrdering) { + var b = new BytesRefArrayBlock(values, pc, firstValueIndexes, nulls, mvOrdering, this); adjustBreaker(b.ramBytesUsed() - values.bigArraysRamBytesUsed(), true); return b; } diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-BlockBuilder.java.st b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-BlockBuilder.java.st index 0ccfc45f1866..241dba127209 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-BlockBuilder.java.st +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-BlockBuilder.java.st @@ -281,26 +281,17 @@ $if(BytesRef)$ values = null; $else$ if (hasNonNullValue && positionCount == 1 && valueCount == 1) { - block = new Constant$Type$Vector(values[0], 1, blockFactory).asBlock(); + block = blockFactory.newConstant$Type$BlockWith(values[0], 1, estimatedBytes); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } if (isDense() && singleValued()) { - block = new $Type$ArrayVector(values, positionCount, blockFactory).asBlock(); + block = blockFactory.new$Type$ArrayVector(values, positionCount, estimatedBytes).asBlock(); } else { - block = new $Type$ArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, blockFactory); + block = blockFactory.new$Type$ArrayBlock(values, positionCount, firstValueIndexes, nullsMask, mvOrdering, estimatedBytes); } } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(block.ramBytesUsed() - estimatedBytes, false); $endif$ built(); return block; diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-VectorBuilder.java.st b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-VectorBuilder.java.st index 1e243c49b5d8..3241a372b7d5 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-VectorBuilder.java.st +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-VectorBuilder.java.st @@ -114,22 +114,13 @@ $if(BytesRef)$ values = null; $else$ if (valueCount == 1) { - vector = new Constant$Type$Vector(values[0], 1, blockFactory); + vector = blockFactory.newConstant$Type$BlockWith(values[0], 1, estimatedBytes).asVector(); } else { if (values.length - valueCount > 1024 || valueCount < (values.length / 2)) { values = Arrays.copyOf(values, valueCount); } - vector = new $Type$ArrayVector(values, valueCount, blockFactory); + vector = blockFactory.new$Type$ArrayVector(values, valueCount, estimatedBytes); } - /* - * Update the breaker with the actual bytes used. - * We pass false below even though we've used the bytes. That's weird, - * but if we break here we will throw away the used memory, letting - * it be deallocated. The exception will bubble up and the builder will - * still technically be open, meaning the calling code should close it - * which will return all used memory to the breaker. - */ - blockFactory.adjustBreaker(vector.ramBytesUsed() - estimatedBytes, false); $endif$ built(); return vector; diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-VectorFixedBuilder.java.st b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-VectorFixedBuilder.java.st index d732c85db746..6cbc9e663981 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-VectorFixedBuilder.java.st +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/X-VectorFixedBuilder.java.st @@ -18,6 +18,7 @@ import org.apache.lucene.util.RamUsageEstimator; final class $Type$VectorFixedBuilder implements $Type$Vector.FixedBuilder { private final BlockFactory blockFactory; private final $type$[] values; + private final long preAdjustedBytes; /** * The next value to write into. {@code -1} means the vector has already * been built. @@ -25,7 +26,8 @@ final class $Type$VectorFixedBuilder implements $Type$Vector.FixedBuilder { private int nextIndex; $Type$VectorFixedBuilder(int size, BlockFactory blockFactory) { - blockFactory.adjustBreaker(ramBytesUsed(size), false); + preAdjustedBytes = ramBytesUsed(size); + blockFactory.adjustBreaker(preAdjustedBytes, false); this.blockFactory = blockFactory; this.values = new $type$[size]; } @@ -54,16 +56,16 @@ final class $Type$VectorFixedBuilder implements $Type$Vector.FixedBuilder { } nextIndex = -1; if (values.length == 1) { - return new Constant$Type$Vector(values[0], 1, blockFactory); + return blockFactory.newConstant$Type$BlockWith(values[0], 1, preAdjustedBytes).asVector(); } - return new $Type$ArrayVector(values, values.length, blockFactory); + return blockFactory.new$Type$ArrayVector(values, values.length, preAdjustedBytes); } @Override public void close() { if (nextIndex >= 0) { // If nextIndex < 0 we've already built the vector - blockFactory.adjustBreaker(-ramBytesUsed(values.length), false); + blockFactory.adjustBreaker(-preAdjustedBytes, false); } } } diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderTests.java index 2179e68c4783..3c822da7b558 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderTests.java @@ -39,16 +39,18 @@ public static List params() { private final ElementType elementType; + BlockFactory blockFactory = BlockFactoryTests.blockFactory(ByteSizeValue.ofGb(1)); + public BlockBuilderTests(ElementType elementType) { this.elementType = elementType; } public void testAllNulls() { for (int numEntries : List.of(1, randomIntBetween(1, 100))) { - testAllNullsImpl(elementType.newBlockBuilder(0), numEntries); - testAllNullsImpl(elementType.newBlockBuilder(100), numEntries); - testAllNullsImpl(elementType.newBlockBuilder(1000), numEntries); - testAllNullsImpl(elementType.newBlockBuilder(randomIntBetween(0, 100)), numEntries); + testAllNullsImpl(elementType.newBlockBuilder(0, blockFactory), numEntries); + testAllNullsImpl(elementType.newBlockBuilder(100, blockFactory), numEntries); + testAllNullsImpl(elementType.newBlockBuilder(1000, blockFactory), numEntries); + testAllNullsImpl(elementType.newBlockBuilder(randomIntBetween(0, 100), blockFactory), numEntries); } } @@ -56,11 +58,13 @@ private void testAllNullsImpl(Block.Builder builder, int numEntries) { for (int i = 0; i < numEntries; i++) { builder.appendNull(); } - Block block = builder.build(); - assertThat(block.getPositionCount(), is(numEntries)); - assertThat(block.isNull(0), is(true)); - assertThat(block.isNull(numEntries - 1), is(true)); - assertThat(block.isNull(randomPosition(numEntries)), is(true)); + try (Block block = builder.build()) { + assertThat(block.getPositionCount(), is(numEntries)); + assertThat(block.isNull(0), is(true)); + assertThat(block.isNull(numEntries - 1), is(true)); + assertThat(block.isNull(randomPosition(numEntries)), is(true)); + } + assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } static int randomPosition(int positionCount) { @@ -68,7 +72,6 @@ static int randomPosition(int positionCount) { } public void testCloseWithoutBuilding() { - BlockFactory blockFactory = BlockFactoryTests.blockFactory(ByteSizeValue.ofGb(1)); elementType.newBlockBuilder(10, blockFactory).close(); assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } @@ -110,7 +113,6 @@ public void testBuildSingle() { } private void testBuild(int size, boolean nullable, int maxValueCount) { - BlockFactory blockFactory = BlockFactoryTests.blockFactory(ByteSizeValue.ofGb(1)); try (Block.Builder builder = elementType.newBlockBuilder(randomBoolean() ? size : 1, blockFactory)) { BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, size, nullable, 1, maxValueCount, 0, 0); builder.copyFrom(random.block(), 0, random.block().getPositionCount()); @@ -124,7 +126,6 @@ private void testBuild(int size, boolean nullable, int maxValueCount) { } public void testDoubleBuild() { - BlockFactory blockFactory = BlockFactoryTests.blockFactory(ByteSizeValue.ofGb(1)); try (Block.Builder builder = elementType.newBlockBuilder(10, blockFactory)) { BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, 10, false, 1, 1, 0, 0); builder.copyFrom(random.block(), 0, random.block().getPositionCount()); @@ -142,19 +143,43 @@ public void testDoubleBuild() { public void testCranky() { BigArrays bigArrays = new MockBigArrays(PageCacheRecycler.NON_RECYCLING_INSTANCE, new CrankyCircuitBreakerService()); BlockFactory blockFactory = new BlockFactory(bigArrays.breakerService().getBreaker(CircuitBreaker.REQUEST), bigArrays); - try { - try (Block.Builder builder = elementType.newBlockBuilder(10, blockFactory)) { - BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, 10, false, 1, 1, 0, 0); - builder.copyFrom(random.block(), 0, random.block().getPositionCount()); - try (Block built = builder.build()) { - assertThat(built, equalTo(random.block())); + for (int i = 0; i < 100; i++) { + try { + try (Block.Builder builder = elementType.newBlockBuilder(10, blockFactory)) { + BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, 10, false, 1, 1, 0, 0); + builder.copyFrom(random.block(), 0, random.block().getPositionCount()); + try (Block built = builder.build()) { + assertThat(built, equalTo(random.block())); + } } + // If we made it this far cranky didn't fail us! + } catch (CircuitBreakingException e) { + logger.info("cranky", e); + assertThat(e.getMessage(), equalTo(CrankyCircuitBreakerService.ERROR_MESSAGE)); } - // If we made it this far cranky didn't fail us! - } catch (CircuitBreakingException e) { - logger.info("cranky", e); - assertThat(e.getMessage(), equalTo(CrankyCircuitBreakerService.ERROR_MESSAGE)); + assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); + } + } + + public void testCrankyConstantBlock() { + BigArrays bigArrays = new MockBigArrays(PageCacheRecycler.NON_RECYCLING_INSTANCE, new CrankyCircuitBreakerService()); + BlockFactory blockFactory = new BlockFactory(bigArrays.breakerService().getBreaker(CircuitBreaker.REQUEST), bigArrays); + for (int i = 0; i < 100; i++) { + try { + try (Block.Builder builder = elementType.newBlockBuilder(randomInt(10), blockFactory)) { + BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, 1, false, 1, 1, 0, 0); + builder.copyFrom(random.block(), 0, random.block().getPositionCount()); + try (Block built = builder.build()) { + assertThat(built.asVector().isConstant(), is(true)); + assertThat(built, equalTo(random.block())); + } + } + // If we made it this far cranky didn't fail us! + } catch (CircuitBreakingException e) { + logger.info("cranky", e); + assertThat(e.getMessage(), equalTo(CrankyCircuitBreakerService.ERROR_MESSAGE)); + } + assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } - assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } } diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/VectorBuilderTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/VectorBuilderTests.java index 656d79070f21..04ccf47ea612 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/VectorBuilderTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/VectorBuilderTests.java @@ -93,20 +93,22 @@ public void testDoubleBuild() { public void testCranky() { BigArrays bigArrays = new MockBigArrays(PageCacheRecycler.NON_RECYCLING_INSTANCE, new CrankyCircuitBreakerService()); BlockFactory blockFactory = new BlockFactory(bigArrays.breakerService().getBreaker(CircuitBreaker.REQUEST), bigArrays); - try { - try (Vector.Builder builder = vectorBuilder(10, blockFactory)) { - BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, 10, false, 1, 1, 0, 0); - fill(builder, random.block().asVector()); - try (Vector built = builder.build()) { - assertThat(built, equalTo(random.block().asVector())); + for (int i = 0; i < 100; i++) { + try { + try (Vector.Builder builder = vectorBuilder(10, blockFactory)) { + BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, 10, false, 1, 1, 0, 0); + fill(builder, random.block().asVector()); + try (Vector built = builder.build()) { + assertThat(built, equalTo(random.block().asVector())); + } } + // If we made it this far cranky didn't fail us! + } catch (CircuitBreakingException e) { + logger.info("cranky", e); + assertThat(e.getMessage(), equalTo(CrankyCircuitBreakerService.ERROR_MESSAGE)); } - // If we made it this far cranky didn't fail us! - } catch (CircuitBreakingException e) { - logger.info("cranky", e); - assertThat(e.getMessage(), equalTo(CrankyCircuitBreakerService.ERROR_MESSAGE)); + assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } - assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } private Vector.Builder vectorBuilder(int estimatedSize, BlockFactory blockFactory) { diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/VectorFixedBuilderTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/VectorFixedBuilderTests.java index df67ee2e7822..3c46fef7e525 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/VectorFixedBuilderTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/VectorFixedBuilderTests.java @@ -96,19 +96,21 @@ public void testDoubleBuild() { public void testCranky() { BigArrays bigArrays = new MockBigArrays(PageCacheRecycler.NON_RECYCLING_INSTANCE, new CrankyCircuitBreakerService()); BlockFactory blockFactory = new BlockFactory(bigArrays.breakerService().getBreaker(CircuitBreaker.REQUEST), bigArrays); - try { - Vector.Builder builder = vectorBuilder(10, blockFactory); - BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, 10, false, 1, 1, 0, 0); - fill(builder, random.block().asVector()); - try (Vector built = builder.build()) { - assertThat(built, equalTo(random.block().asVector())); + for (int i = 0; i < 100; i++) { + try { + Vector.Builder builder = vectorBuilder(10, blockFactory); + BasicBlockTests.RandomBlock random = BasicBlockTests.randomBlock(elementType, 10, false, 1, 1, 0, 0); + fill(builder, random.block().asVector()); + try (Vector built = builder.build()) { + assertThat(built, equalTo(random.block().asVector())); + } + // If we made it this far cranky didn't fail us! + } catch (CircuitBreakingException e) { + logger.info("cranky", e); + assertThat(e.getMessage(), equalTo(CrankyCircuitBreakerService.ERROR_MESSAGE)); } - // If we made it this far cranky didn't fail us! - } catch (CircuitBreakingException e) { - logger.info("cranky", e); - assertThat(e.getMessage(), equalTo(CrankyCircuitBreakerService.ERROR_MESSAGE)); + assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } - assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } private Vector.Builder vectorBuilder(int size, BlockFactory blockFactory) {