perf: optimize bucket counting and tracking in LongKeyedBucketOrds#22450
perf: optimize bucket counting and tracking in LongKeyedBucketOrds#22450rajat315315 wants to merge 1 commit into
Conversation
PR Reviewer Guide 🔍(Review updated until commit ccec60b)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to ccec60b
Previous suggestionsSuggestions up to commit aba4ca9
|
… maintaining per-bucket counts and max ordinal metadata. Signed-off-by: Your Name <rajatjain.ix@gmail.com>
aba4ca9 to
ccec60b
Compare
|
Persistent review updated to latest commit ccec60b |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #22450 +/- ##
============================================
+ Coverage 73.39% 73.46% +0.06%
- Complexity 76397 76495 +98
============================================
Files 6105 6104 -1
Lines 346613 346566 -47
Branches 49888 49880 -8
============================================
+ Hits 254403 254594 +191
+ Misses 71958 71722 -236
+ Partials 20252 20250 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
msfroh
left a comment
There was a problem hiding this comment.
Thanks @rajat315315 !
This looks good overall. I left some pretty minor cleanup comments.
| if (ord >= 0) { | ||
| maxOwningBucketOrd = Math.max(maxOwningBucketOrd, owningBucketOrd); | ||
| bucketOrdsCounts = bigArrays.grow(bucketOrdsCounts, owningBucketOrd + 1); | ||
| bucketOrdsCounts.set(owningBucketOrd, bucketOrdsCounts.get(owningBucketOrd) + 1); |
There was a problem hiding this comment.
You can use bucketOrdsCounts.increment(owningBucketOrd, 1). It might help performance just a little bit, but also IMO it's more readable.
| maxOwningBucketOrd = Math.max(maxOwningBucketOrd, owningBucketOrd); | ||
| bucketOrdsCounts = bigArrays.grow(bucketOrdsCounts, owningBucketOrd + 1); |
There was a problem hiding this comment.
I feel like we can slightly reduce the number of comparisons here (which normally I wouldn't worry about, but it is in the critical path, so it might actually be worth it).
What if we make this:
if (owningBucketOrd > maxOwningBucketOrd) {
maxOwningBucketOrd = owningBucketOrd;
bucketOrdsCounts = bigArrays.grow(bucketOrdsCounts, owningBucketOrd + 1);
}
Basically, we get two comparisons for the price of one. What do you think?
| try { | ||
| ords.close(); | ||
| } finally { | ||
| if (bucketOrdsCounts != null) { | ||
| bucketOrdsCounts.close(); | ||
| } | ||
| } |
There was a problem hiding this comment.
A couple of things here:
ords.close()should never throw an exception, so I don't believe thetryis necessary.bucketOrdsCountsshould never benull(since it's allocated in the constructor). So I don't think we need thenullcheck.
Description
This PR optimizes$O(N)$ linear scans in $O(1)$ operations:
LongKeyedBucketOrds.FromManyto replacebucketsInOrdandmaxOwningBucketOrdwithmaxOwningBucketOrddynamically as a class field updated on insertions.owningBucketOrdin aLongArraymanaged byBigArrays, incrementing it incrementally.Tests and Verification
./gradlew :server:test --tests "org.opensearch.search.aggregations.bucket.terms.LongKeyedBucketOrdsTests"passed successfully../gradlew spotlessJavaCheck.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
Related Issues
Resolves #22449
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.