-
Notifications
You must be signed in to change notification settings - Fork 3k
Optimize sub aggregation using bulk collection lucene apis #19737
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
jainankitk
wants to merge
38
commits into
opensearch-project:feature/3.x-lucene
from
jainankitk:agg-perf-lucene
Closed
Changes from all commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
469cf51
Combining filter rewrite and skip list approaches for further optimiz…
jainankitk e20f702
Removing parent aggregation check for perf benchmark
jainankitk 82bc95d
Adding changelog entry
jainankitk aff3dc6
Applying the skip list optimization for AutoDateHistogram
jainankitk 1c29540
Addressing checkstyle failures
jainankitk b9e9f2b
Apply spotless
jainankitk a28b9c1
Merge branch 'main' into agg-perf
jainankitk 0a9ef40
Minor bug fix
jainankitk 8d4ccf7
Merge branch 'main' into agg-perf
jainankitk 3cd5f64
Updating to lucene 10.4 snapshot
jainankitk 2c657e7
Using bulk collect APIs in Lucene
jainankitk 879bfaf
Apply spotless
jainankitk 128b9b4
Fixing build issues after changing to 10.4 lucene snapshot
jainankitk 65192fd
Fixing Lucene103Codec references in test files
jainankitk 931614c
Updating Lucene version for ES
jainankitk 866937d
Merge branch 'main' into agg-perf
jainankitk 2d697fc
Updating Lucene codec version for ES
jainankitk e04a1b4
Adding CompositeCodec104 changes
jainankitk 45512cd
Remaining CompositeCodec104 changes
jainankitk 729bf0a
Final CompositeCodec104 changes
jainankitk 4e7d9e6
Merge branch 'main' into agg-perf
jainankitk 09d5c71
Merge branch 'feature/3.x-lucene' into agg-perf-lucene
jainankitk 23fbad3
Add unit test for filter rewrite with date histogram with skiplist.
asimmahmood1 7eb64f7
Spotless check
asimmahmood1 35834e4
Fix unit test
asimmahmood1 2b593c9
Merge remote-tracking branch 'upstream/main' into agg-perf
asimmahmood1 3cdc37d
Not ready for check-in, just throwing this out to come up with differ…
asimmahmood1 d0eeb37
Revert auto date changes for this PR
asimmahmood1 66ffef1
Merge remote-tracking branch 'upstream/main' into agg-perf
asimmahmood1 0ec357a
Switch to Lucene's version of BitSetDocIdStream
asimmahmood1 7a7209f
Merge remote-tracking branch 'upstream/main' into agg-perf
asimmahmood1 37f4641
Merge branch 'main' into agg-perf
jainankitk eaf7e52
Resolving merge conflict issue
jainankitk 4d9dd28
Merge branch 'feature/3.x-lucene' into agg-perf-lucene
jainankitk 8403592
Merge branch 'agg-perf' into agg-perf-lucene
jainankitk 80079be
Fixing build failure
jainankitk e90eaca
Merge branch 'feature/3.x-lucene' into agg-perf-lucene
jainankitk 17c6b7a
Merge branch 'feature/3.x-lucene' into agg-perf-lucene
jainankitk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
173 changes: 173 additions & 0 deletions
173
...c/main/java/org/opensearch/search/aggregations/bucket/HistogramSkiplistLeafCollector.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| /* | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * The OpenSearch Contributors require contributions made to | ||
| * this file be licensed under the Apache-2.0 license or a | ||
| * compatible open source license. | ||
| */ | ||
|
|
||
| package org.opensearch.search.aggregations.bucket; | ||
|
|
||
| import org.apache.lucene.index.DocValuesSkipper; | ||
| import org.apache.lucene.index.NumericDocValues; | ||
| import org.apache.lucene.search.DocIdStream; | ||
| import org.apache.lucene.search.Scorable; | ||
| import org.opensearch.common.Rounding; | ||
| import org.opensearch.search.aggregations.LeafBucketCollector; | ||
| import org.opensearch.search.aggregations.bucket.terms.LongKeyedBucketOrds; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| /** | ||
| * Histogram collection logic using skip list. | ||
| * | ||
| * @opensearch.internal | ||
| */ | ||
| public class HistogramSkiplistLeafCollector extends LeafBucketCollector { | ||
|
|
||
| private final NumericDocValues values; | ||
| private final DocValuesSkipper skipper; | ||
| private final Rounding.Prepared preparedRounding; | ||
| private final LongKeyedBucketOrds bucketOrds; | ||
| private final LeafBucketCollector sub; | ||
| private final BucketsAggregator aggregator; | ||
|
|
||
| /** | ||
| * Max doc ID (inclusive) up to which all docs values may map to the same | ||
| * bucket. | ||
| */ | ||
| private int upToInclusive = -1; | ||
|
|
||
| /** | ||
| * Whether all docs up to {@link #upToInclusive} values map to the same bucket. | ||
| */ | ||
| private boolean upToSameBucket; | ||
|
|
||
| /** | ||
| * Index in bucketOrds for docs up to {@link #upToInclusive}. | ||
| */ | ||
| private long upToBucketIndex; | ||
|
|
||
| public HistogramSkiplistLeafCollector( | ||
| NumericDocValues values, | ||
| DocValuesSkipper skipper, | ||
| Rounding.Prepared preparedRounding, | ||
| LongKeyedBucketOrds bucketOrds, | ||
| LeafBucketCollector sub, | ||
| BucketsAggregator aggregator | ||
| ) { | ||
| this.values = values; | ||
| this.skipper = skipper; | ||
| this.preparedRounding = preparedRounding; | ||
| this.bucketOrds = bucketOrds; | ||
| this.sub = sub; | ||
| this.aggregator = aggregator; | ||
| } | ||
|
|
||
| @Override | ||
| public void setScorer(Scorable scorer) throws IOException { | ||
| if (sub != null) { | ||
| sub.setScorer(scorer); | ||
| } | ||
| } | ||
|
|
||
| private void advanceSkipper(int doc, long owningBucketOrd) throws IOException { | ||
| if (doc > skipper.maxDocID(0)) { | ||
| skipper.advance(doc); | ||
| } | ||
| upToSameBucket = false; | ||
|
|
||
| if (skipper.minDocID(0) > doc) { | ||
| // Corner case which happens if `doc` doesn't have a value and is between two | ||
| // intervals of | ||
| // the doc-value skip index. | ||
| upToInclusive = skipper.minDocID(0) - 1; | ||
| return; | ||
| } | ||
|
|
||
| upToInclusive = skipper.maxDocID(0); | ||
|
|
||
| // Now find the highest level where all docs map to the same bucket. | ||
| for (int level = 0; level < skipper.numLevels(); ++level) { | ||
| int totalDocsAtLevel = skipper.maxDocID(level) - skipper.minDocID(level) + 1; | ||
| long minBucket = preparedRounding.round(skipper.minValue(level)); | ||
| long maxBucket = preparedRounding.round(skipper.maxValue(level)); | ||
|
|
||
| if (skipper.docCount(level) == totalDocsAtLevel && minBucket == maxBucket) { | ||
| // All docs at this level have a value, and all values map to the same bucket. | ||
| upToInclusive = skipper.maxDocID(level); | ||
| upToSameBucket = true; | ||
| upToBucketIndex = bucketOrds.add(owningBucketOrd, maxBucket); | ||
| if (upToBucketIndex < 0) { | ||
| upToBucketIndex = -1 - upToBucketIndex; | ||
| } | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void collect(int doc, long owningBucketOrd) throws IOException { | ||
| if (doc > upToInclusive) { | ||
| advanceSkipper(doc, owningBucketOrd); | ||
| } | ||
|
|
||
| if (upToSameBucket) { | ||
| aggregator.incrementBucketDocCount(upToBucketIndex, 1L); | ||
| sub.collect(doc, upToBucketIndex); | ||
| } else if (values.advanceExact(doc)) { | ||
| final long value = values.longValue(); | ||
| long bucketIndex = bucketOrds.add(owningBucketOrd, preparedRounding.round(value)); | ||
| if (bucketIndex < 0) { | ||
| bucketIndex = -1 - bucketIndex; | ||
| aggregator.collectExistingBucket(sub, doc, bucketIndex); | ||
| } else { | ||
| aggregator.collectBucket(sub, doc, bucketIndex); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void collect(DocIdStream stream) throws IOException { | ||
| // This will only be called if its the top agg | ||
| collect(stream, 0); | ||
| } | ||
|
|
||
| @Override | ||
| public void collect(DocIdStream stream, long owningBucketOrd) throws IOException { | ||
| // This will only be called if its the sub aggregation | ||
| for (;;) { | ||
| int upToExclusive = upToInclusive + 1; | ||
| if (upToExclusive < 0) { // overflow | ||
| upToExclusive = Integer.MAX_VALUE; | ||
| } | ||
|
|
||
| if (upToSameBucket) { | ||
| if (sub == NO_OP_COLLECTOR) { | ||
| // stream.count maybe faster when we don't need to handle sub-aggs | ||
| long count = stream.count(upToExclusive); | ||
| aggregator.incrementBucketDocCount(upToBucketIndex, count); | ||
| } else { | ||
| int count = 0; | ||
| int[] docBuffer = new int[64]; | ||
| int cnt = Integer.MAX_VALUE; | ||
| while (cnt != 0) { | ||
| cnt = stream.intoArray(upToExclusive, docBuffer); | ||
| sub.collect(docBuffer, upToBucketIndex); | ||
| count += cnt; | ||
| } | ||
| aggregator.incrementBucketDocCount(upToBucketIndex, count); | ||
| } | ||
| } else { | ||
| stream.forEach(upToExclusive, doc -> collect(doc, owningBucketOrd)); | ||
| } | ||
|
|
||
| if (stream.mayHaveRemaining()) { | ||
| advanceSkipper(upToExclusive, owningBucketOrd); | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } | ||
24 changes: 24 additions & 0 deletions
24
...r/src/main/java/org/opensearch/search/aggregations/bucket/filterrewrite/BFSCollector.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * The OpenSearch Contributors require contributions made to | ||
| * this file be licensed under the Apache-2.0 license or a | ||
| * compatible open source license. | ||
| */ | ||
|
|
||
| package org.opensearch.search.aggregations.bucket.filterrewrite; | ||
|
|
||
| import org.apache.lucene.index.LeafReaderContext; | ||
| import org.opensearch.search.aggregations.LeafBucketCollector; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| /** | ||
| * Workaround for collectors that cannot handle DFS travel, i.e. changing owningBucketOrd) | ||
| * | ||
| * @opensearch.internal | ||
| */ | ||
| public interface BFSCollector { | ||
|
|
||
| LeafBucketCollector getBFSLeafCollector(LeafReaderContext ctx) throws IOException; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the issue here is when
cntis less thandocBuffer.length,sub.collect(docBuffer, upToBucketIndex);will still iterate through entire docBuffer.So we can either pass in size e.g.
sub.collect(docBuffer, cnt, upToBucketIndex);Or create a new array, which I think will be sub optimal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I realized this yesterday. Missed adding a comment. Due to this issue
advanceExactmight be getting invoked fortarget>docresulting in an error