99package org .elasticsearch .search .aggregations .bucket ;
1010
1111import org .apache .lucene .index .LeafReaderContext ;
12- import org .elasticsearch .common .breaker .CircuitBreaker ;
1312import org .elasticsearch .common .util .IntArray ;
1413import org .elasticsearch .common .util .LongArray ;
1514import org .elasticsearch .common .util .ObjectArray ;
4241import java .util .function .ToLongFunction ;
4342
4443public abstract class BucketsAggregator extends AggregatorBase {
45- private final CircuitBreaker breaker ;
44+
4645 private LongArray docCounts ;
4746 protected final DocCountProvider docCountProvider ;
48- private int callCount ;
4947
5048 @ SuppressWarnings ("this-escape" )
5149 public BucketsAggregator (
@@ -57,7 +55,6 @@ public BucketsAggregator(
5755 Map <String , Object > metadata
5856 ) throws IOException {
5957 super (name , factories , aggCtx , parent , bucketCardinality , metadata );
60- breaker = aggCtx .breaker ();
6158 docCounts = bigArrays ().newLongArray (1 , true );
6259 docCountProvider = new DocCountProvider ();
6360 }
@@ -83,7 +80,7 @@ public final void collectBucket(LeafBucketCollector subCollector, int doc, long
8380 grow (bucketOrd + 1 );
8481 int docCount = docCountProvider .getDocCount (doc );
8582 if (docCounts .increment (bucketOrd , docCount ) == docCount ) {
86- updateCircuitBreaker ("allocated_buckets" );
83+ checkRealMemoryCB ("allocated_buckets" );
8784 }
8885 subCollector .collect (doc , bucketOrd );
8986 }
@@ -176,7 +173,7 @@ protected final IntFunction<InternalAggregations> buildSubAggsForBuckets(LongArr
176173 prepareSubAggs (bucketOrdsToCollect );
177174 InternalAggregation [][] aggregations = new InternalAggregation [subAggregators .length ][];
178175 for (int i = 0 ; i < subAggregators .length ; i ++) {
179- updateCircuitBreaker ("building_sub_aggregation" );
176+ checkRealMemoryCB ("building_sub_aggregation" );
180177 aggregations [i ] = subAggregators [i ].buildAggregations (bucketOrdsToCollect );
181178 }
182179 return subAggsForBucketFunction (aggregations );
@@ -247,31 +244,30 @@ protected final <B> InternalAggregation[] buildAggregationsForFixedBucketCount(
247244 Function <List <B >, InternalAggregation > resultBuilder
248245 ) throws IOException {
249246 try (LongArray bucketOrdsToCollect = bigArrays ().newLongArray (owningBucketOrds .size () * bucketsPerOwningBucketOrd )) {
250- int bucketOrdIdx = 0 ;
247+ final int [] bucketOrdIdx = new int [] { 0 } ;
251248 for (long i = 0 ; i < owningBucketOrds .size (); i ++) {
252249 long ord = owningBucketOrds .get (i ) * bucketsPerOwningBucketOrd ;
253250 for (int offsetInOwningOrd = 0 ; offsetInOwningOrd < bucketsPerOwningBucketOrd ; offsetInOwningOrd ++) {
254- bucketOrdsToCollect .set (bucketOrdIdx ++, ord ++);
251+ bucketOrdsToCollect .set (bucketOrdIdx [ 0 ] ++, ord ++);
255252 }
256253 }
257- bucketOrdIdx = 0 ;
254+ bucketOrdIdx [ 0 ] = 0 ;
258255 var subAggregationResults = buildSubAggsForBuckets (bucketOrdsToCollect );
259256
260- InternalAggregation [] results = new InternalAggregation [Math .toIntExact (owningBucketOrds .size ())];
261- for (int owningOrdIdx = 0 ; owningOrdIdx < results .length ; owningOrdIdx ++) {
257+ return buildAggregations (Math .toIntExact (owningBucketOrds .size ()), ordIdx -> {
262258 List <B > buckets = new ArrayList <>(bucketsPerOwningBucketOrd );
263259 for (int offsetInOwningOrd = 0 ; offsetInOwningOrd < bucketsPerOwningBucketOrd ; offsetInOwningOrd ++) {
260+ checkRealMemoryCBForInternalBucket ();
264261 buckets .add (
265262 bucketBuilder .build (
266263 offsetInOwningOrd ,
267- bucketDocCount (bucketOrdsToCollect .get (bucketOrdIdx )),
268- subAggregationResults .apply (bucketOrdIdx ++)
264+ bucketDocCount (bucketOrdsToCollect .get (bucketOrdIdx [ 0 ] )),
265+ subAggregationResults .apply (bucketOrdIdx [ 0 ] ++)
269266 )
270267 );
271268 }
272- results [owningOrdIdx ] = resultBuilder .apply (buckets );
273- }
274- return results ;
269+ return resultBuilder .apply (buckets );
270+ });
275271 }
276272 }
277273
@@ -295,11 +291,10 @@ protected final InternalAggregation[] buildAggregationsForSingleBucket(
295291 * here but we don't because single bucket aggs never have.
296292 */
297293 var subAggregationResults = buildSubAggsForBuckets (owningBucketOrds );
298- InternalAggregation [] results = new InternalAggregation [Math .toIntExact (owningBucketOrds .size ())];
299- for (int ordIdx = 0 ; ordIdx < results .length ; ordIdx ++) {
300- results [ordIdx ] = resultBuilder .build (owningBucketOrds .get (ordIdx ), subAggregationResults .apply (ordIdx ));
301- }
302- return results ;
294+ return buildAggregations (
295+ Math .toIntExact (owningBucketOrds .size ()),
296+ ordIdx -> resultBuilder .build (owningBucketOrds .get (ordIdx ), subAggregationResults .apply (ordIdx ))
297+ );
303298 }
304299
305300 @ FunctionalInterface
@@ -335,37 +330,36 @@ protected final <B> InternalAggregation[] buildAggregationsForVariableBuckets(
335330 );
336331 }
337332 try (LongArray bucketOrdsToCollect = bigArrays ().newLongArray (totalOrdsToCollect )) {
338- int b = 0 ;
333+ final int [] b = new int [] { 0 } ;
339334 for (long i = 0 ; i < owningBucketOrds .size (); i ++) {
340335 LongKeyedBucketOrds .BucketOrdsEnum ordsEnum = bucketOrds .ordsEnum (owningBucketOrds .get (i ));
341336 while (ordsEnum .next ()) {
342- bucketOrdsToCollect .set (b ++, ordsEnum .ord ());
337+ bucketOrdsToCollect .set (b [ 0 ] ++, ordsEnum .ord ());
343338 }
344339 }
345340 var subAggregationResults = buildSubAggsForBuckets (bucketOrdsToCollect );
346341
347- InternalAggregation [] results = new InternalAggregation [Math .toIntExact (owningBucketOrds .size ())];
348- b = 0 ;
349- for (int ordIdx = 0 ; ordIdx < results .length ; ordIdx ++) {
342+ b [0 ] = 0 ;
343+ return buildAggregations (Math .toIntExact (owningBucketOrds .size ()), ordIdx -> {
350344 final long owningBucketOrd = owningBucketOrds .get (ordIdx );
351345 List <B > buckets = new ArrayList <>(bucketsInOrd .get (ordIdx ));
352346 LongKeyedBucketOrds .BucketOrdsEnum ordsEnum = bucketOrds .ordsEnum (owningBucketOrd );
353347 while (ordsEnum .next ()) {
354- if (bucketOrdsToCollect .get (b ) != ordsEnum .ord ()) {
348+ if (bucketOrdsToCollect .get (b [ 0 ] ) != ordsEnum .ord ()) {
355349 // If we hit this, something has gone horribly wrong and we need to investigate
356350 throw AggregationErrors .iterationOrderChangedWithoutMutating (
357351 bucketOrds .toString (),
358352 ordsEnum .ord (),
359- bucketOrdsToCollect .get (b )
353+ bucketOrdsToCollect .get (b [ 0 ] )
360354 );
361355 }
356+ checkRealMemoryCBForInternalBucket ();
362357 buckets .add (
363- bucketBuilder .build (ordsEnum .value (), bucketDocCount (ordsEnum .ord ()), subAggregationResults .apply (b ++))
358+ bucketBuilder .build (ordsEnum .value (), bucketDocCount (ordsEnum .ord ()), subAggregationResults .apply (b [ 0 ] ++))
364359 );
365360 }
366- results [ordIdx ] = resultBuilder .build (owningBucketOrd , buckets );
367- }
368- return results ;
361+ return resultBuilder .build (owningBucketOrd , buckets );
362+ });
369363 }
370364 }
371365 }
@@ -425,14 +419,9 @@ protected void preGetSubLeafCollectors(LeafReaderContext ctx) throws IOException
425419 docCountProvider .setLeafReaderContext (ctx );
426420 }
427421
428- /**
429- * This method calls the circuit breaker from time to time in order to give it a chance to check available
430- * memory in the parent breaker (Which should be a real memory breaker) and break the execution if we are running out.
431- * To achieve that, we are passing 0 as the estimated bytes every 1024 calls
432- */
433- private void updateCircuitBreaker (String label ) {
434- if ((++callCount & 0x3FF ) == 0 ) {
435- breaker .addEstimateBytesAndMaybeBreak (0 , label );
436- }
422+ /** This method should be called whenever a new bucket object is created. It will check the real memory
423+ * circuit breaker in a sampling fashion. See {@link #checkRealMemoryCB(String)} */
424+ protected final void checkRealMemoryCBForInternalBucket () {
425+ checkRealMemoryCB ("internal_bucket" );
437426 }
438427}
0 commit comments