3434
3535import org .opensearch .common .lease .Releasable ;
3636import org .opensearch .common .util .BigArrays ;
37+ import org .opensearch .common .util .LongArray ;
3738import org .opensearch .common .util .LongLongHash ;
3839import org .opensearch .common .util .ReorganizingLongHash ;
3940import org .opensearch .search .aggregations .CardinalityUpperBound ;
@@ -229,16 +230,27 @@ public void close() {
229230 * @opensearch.internal
230231 */
231232 public static class FromMany extends LongKeyedBucketOrds {
233+ private final BigArrays bigArrays ;
232234 private final LongLongHash ords ;
235+ private long maxOwningBucketOrd = -1 ;
236+ private LongArray bucketOrdsCounts ;
233237
234238 public FromMany (BigArrays bigArrays ) {
239+ this .bigArrays = bigArrays ;
235240 ords = new LongLongHash (2 , bigArrays );
241+ bucketOrdsCounts = bigArrays .newLongArray (1 , true );
236242 }
237243
238244 @ Override
239245 public long add (long owningBucketOrd , long value ) {
240246 // This is in the critical path for collecting most aggs. Be careful of performance.
241- return ords .add (owningBucketOrd , value );
247+ long ord = ords .add (owningBucketOrd , value );
248+ if (ord >= 0 ) {
249+ maxOwningBucketOrd = Math .max (maxOwningBucketOrd , owningBucketOrd );
250+ bucketOrdsCounts = bigArrays .grow (bucketOrdsCounts , owningBucketOrd + 1 );
251+ bucketOrdsCounts .set (owningBucketOrd , bucketOrdsCounts .get (owningBucketOrd ) + 1 );
252+ }
253+ return ord ;
242254 }
243255
244256 @ Override
@@ -253,14 +265,10 @@ public long get(long ordinal) {
253265
254266 @ Override
255267 public long bucketsInOrd (long owningBucketOrd ) {
256- // TODO it'd be faster to count the number of buckets in a list of these ords rather than one at a time
257- long count = 0 ;
258- for (long i = 0 ; i < ords .size (); i ++) {
259- if (ords .getKey1 (i ) == owningBucketOrd ) {
260- count ++;
261- }
268+ if (owningBucketOrd >= bucketOrdsCounts .size ()) {
269+ return 0 ;
262270 }
263- return count ;
271+ return bucketOrdsCounts . get ( owningBucketOrd ) ;
264272 }
265273
266274 @ Override
@@ -270,12 +278,7 @@ public long size() {
270278
271279 @ Override
272280 public long maxOwningBucketOrd () {
273- // TODO this is fairly expensive to compute. Can we avoid needing it?
274- long max = -1 ;
275- for (long i = 0 ; i < ords .size (); i ++) {
276- max = Math .max (max , ords .getKey1 (i ));
277- }
278- return max ;
281+ return maxOwningBucketOrd ;
279282 }
280283
281284 @ Override
@@ -313,7 +316,13 @@ public long ord() {
313316
314317 @ Override
315318 public void close () {
316- ords .close ();
319+ try {
320+ ords .close ();
321+ } finally {
322+ if (bucketOrdsCounts != null ) {
323+ bucketOrdsCounts .close ();
324+ }
325+ }
317326 }
318327 }
319328}
0 commit comments