Save memory when numeric terms agg is not top#55873
Merged
nik9000 merged 21 commits intoelastic:masterfrom May 8, 2020
Merged
Conversation
Right now all implementations of the `terms` agg allocate a new `Aggregator` per bucket. This uses a bunch of memory. Exactly how much isn't clear but each `Aggregator` ends up making its own objects to read doc values which have non-trivial buffers. And it forces all of it sub-aggregations to do the same. We allocate a new `Aggregator` per bucket for two reasons: 1. We didn't have an appropriate data structure to track the sub-ordinals of each parent bucket. 2. You can only make a single call to `runDeferredCollections(long...)` per `Aggregator` which was the only way to delay collection of sub-aggregations. This change adds a way to return "deferred" aggregations from any bucket aggregation and undefers them as part of regular collections. This mechanism allows you to defer without `runDeferredCollections(long...)`. This change also adds a fairly simplistic data structure to track the sub-ordinals for `long`-keyed buckets. It uses both of those to power numeric `terms` aggregations and removes the per-bucket allocation of their `Aggregator`. This fairly substantially reduces memory consumption of numeric `terms` aggregations that are not the "top level", especially when those aggregations contain many sub-aggregations. I picked numeric `terms` aggregations because those have the simplest implementation. At least, I could kind of fit it in my head. And I haven't fully understood the "bytes"-based terms aggregations, but I imagine I'll be able to make similar optimizations to them in follow up changes.
nik9000
commented
Apr 28, 2020
Member
Author
|
@elasticmachine, test this pleas |
nik9000
added a commit
to nik9000/rally-tracks
that referenced
this pull request
Apr 29, 2020
Adds a rally track specifically for testing the performance of the terms agg as I'll be doing some work on it. In particular this focuses on numeric terms because the first phase of my work only touches them. Relates to elastic/elasticsearch#55873
Member
Author
|
This looks like it might actually speed up nested numeric terms. I kind of figured that it'd be a little faster. But these numbers are more than I'd though.... They look real though. |
nik9000
commented
Apr 30, 2020
| @@ -158,19 +158,27 @@ public final InternalAggregation reducePipelines( | |||
|
|
|||
| @Override | |||
| public InternalAggregation copyWithRewritenBuckets(Function<InternalAggregations, InternalAggregations> rewriter) { | |||
Member
Author
|
I've rebuilt this, replacing delaying building results with reworking agg results to be built for the entire aggregator at once. I've push some code that looks to mostly work and will be cleaning it up soon! |
nik9000
commented
May 3, 2020
|
|
||
| @Override | ||
| public BucketComparator bucketComparator(String key, SortOrder order) { | ||
| if (false == this instanceof SingleBucketAggregator) { |
Member
Author
There was a problem hiding this comment.
This was missing from some work that I did previously and removing the wrapping of LongTermsAggregator revealed it.
Member
Author
There was a problem hiding this comment.
Without this we get strange test failures around sorting.
nik9000
added a commit
that referenced
this pull request
Jun 2, 2020
hub-cap
pushed a commit
to elastic/rally-tracks
that referenced
this pull request
Jun 3, 2020
Adds a rally track specifically for testing the performance of the bucket aggs when they are "sub" aggs. Relates to elastic/elasticsearch#55873
hub-cap
pushed a commit
to elastic/rally-tracks
that referenced
this pull request
Jun 3, 2020
Adds a rally track specifically for testing the performance of the bucket aggs when they are "sub" aggs. Relates to elastic/elasticsearch#55873
hub-cap
pushed a commit
to elastic/rally-tracks
that referenced
this pull request
Jun 3, 2020
Adds a rally track specifically for testing the performance of the bucket aggs when they are "sub" aggs. Relates to elastic/elasticsearch#55873
nik9000
added a commit
to nik9000/elasticsearch
that referenced
this pull request
Jun 9, 2020
Reworks the `parent` and `child` aggregation are not at the top level using the optimization from elastic#55873. Instead of wrapping all non-top-level `parent` and `child` aggregators we now handle being a child aggregator in the aggregator, specifically by adding recording which global ordinals show up in the parent and then checking if they match the child.
nik9000
added a commit
that referenced
this pull request
Jun 10, 2020
Reworks the `parent` and `child` aggregation are not at the top level using the optimization from #55873. Instead of wrapping all non-top-level `parent` and `child` aggregators we now handle being a child aggregator in the aggregator, specifically by adding recording which global ordinals show up in the parent and then checking if they match the child.
nik9000
added a commit
to nik9000/elasticsearch
that referenced
this pull request
Jun 10, 2020
Reworks the `parent` and `child` aggregation are not at the top level using the optimization from elastic#55873. Instead of wrapping all non-top-level `parent` and `child` aggregators we now handle being a child aggregator in the aggregator, specifically by adding recording which global ordinals show up in the parent and then checking if they match the child.
nik9000
added a commit
that referenced
this pull request
Jun 10, 2020
Reworks the `parent` and `child` aggregation are not at the top level using the optimization from #55873. Instead of wrapping all non-top-level `parent` and `child` aggregators we now handle being a child aggregator in the aggregator, specifically by adding recording which global ordinals show up in the parent and then checking if they match the child.
nik9000
added a commit
to nik9000/elasticsearch
that referenced
this pull request
Jun 10, 2020
This uses the optimization that we started making in elastic#55873 for `rare_terms` to save a bit of memory when that aggregation is not on the top level.
nik9000
added a commit
that referenced
this pull request
Jun 12, 2020
This uses the optimization that we started making in #55873 for `rare_terms` to save a bit of memory when that aggregation is not on the top level.
nik9000
added a commit
to nik9000/elasticsearch
that referenced
this pull request
Jun 12, 2020
This uses the optimization that we started making in elastic#55873 for `rare_terms` to save a bit of memory when that aggregation is not on the top level.
nik9000
added a commit
that referenced
this pull request
Jun 12, 2020
nik9000
added a commit
to nik9000/elasticsearch
that referenced
this pull request
Jun 15, 2020
This merges the aggregator for `significant_text` into `significant_terms`, applying the optimization built in elastic#55873 to save memory when the aggregation is not on top. The `significant_text` aggregation is pretty memory intensive all on its own and this doesn't particularly help with that, but it'll help with the memory usage of any sub-aggregations.
nik9000
added a commit
that referenced
this pull request
Jun 18, 2020
This merges the aggregator for `significant_text` into `significant_terms`, applying the optimization built in #55873 to save memory when the aggregation is not on top. The `significant_text` aggregation is pretty memory intensive all on its own and this doesn't particularly help with that, but it'll help with the memory usage of any sub-aggregations.
nik9000
added a commit
to nik9000/elasticsearch
that referenced
this pull request
Jun 18, 2020
This merges the aggregator for `significant_text` into `significant_terms`, applying the optimization built in elastic#55873 to save memory when the aggregation is not on top. The `significant_text` aggregation is pretty memory intensive all on its own and this doesn't particularly help with that, but it'll help with the memory usage of any sub-aggregations.
nik9000
added a commit
that referenced
this pull request
Jun 23, 2020
This merges the aggregator for `significant_text` into `significant_terms`, applying the optimization built in #55873 to save memory when the aggregation is not on top. The `significant_text` aggregation is pretty memory intensive all on its own and this doesn't particularly help with that, but it'll help with the memory usage of any sub-aggregations.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Right now all implementations of the
termsagg allocate a newAggregatorper bucket. This uses a bunch of memory. Exactly how muchisn't clear but each
Aggregatorends up making its own objects to readdoc values which have non-trivial buffers. And it forces all of it
sub-aggregations to do the same. We allocate a new
Aggregatorperbucket for two reasons:
sub-ordinals of each parent bucket.
runDeferredCollections(long...)per
Aggregatorwhich was the only way to delay collection ofsub-aggregations.
This change adds a way to return "deferred" aggregations from any
bucket aggregation and undefers them as part of regular collections.
This mechanism allows you to defer without
runDeferredCollections(long...).This change also adds a fairly simplistic data structure to track the
sub-ordinals for
long-keyed buckets.It uses both of those to power numeric
termsaggregations and removesthe per-bucket allocation of their
Aggregator. This fairlysubstantially reduces memory consumption of numeric
termsaggregationsthat are not the "top level", especially when those aggregations contain
many sub-aggregations.
I picked numeric
termsaggregations because those have the simplestimplementation. At least, I could kind of fit it in my head. And I
haven't fully understood the "bytes"-based terms aggregations, but I
imagine I'll be able to make similar optimizations to them in follow up
changes.