Skip to content

Commit cc29af3

Browse files
Speedup a few more aggregations using Kahan summation (#122920)
Follow-up to #120241 and linked issues, using the logic that doesn't require any mutable object indirection led to significant speedups for sum+avg and should be of similar if not more help in these as well.
1 parent 997233f commit cc29af3

File tree

5 files changed

+38
-53
lines changed

5 files changed

+38
-53
lines changed

server/src/main/java/org/elasticsearch/search/aggregations/metrics/AvgAggregator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ protected LeafBucketCollector getLeafCollector(NumericDoubleValues values, final
5858
public void collect(int doc, long bucket) throws IOException {
5959
if (values.advanceExact(doc)) {
6060
maybeGrow(bucket);
61-
computeSum(bucket, values, sums, compensations);
61+
computeSum(bucket, values.doubleValue(), sums, compensations);
6262
counts.increment(bucket, 1L);
6363
}
6464
}

server/src/main/java/org/elasticsearch/search/aggregations/metrics/ExtendedStatsAggregator.java

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ public void collect(int doc, long bucket) throws IOException {
105105

106106
@Override
107107
protected LeafBucketCollector getLeafCollector(NumericDoubleValues values, final LeafBucketCollector sub) {
108-
final CompensatedSum compensatedSum = new CompensatedSum(0, 0);
109108
return new LeafBucketCollectorBase(sub, values) {
110109

111110
@Override
@@ -114,20 +113,9 @@ public void collect(int doc, long bucket) throws IOException {
114113
maybeGrow(bucket);
115114
final double value = values.doubleValue();
116115
counts.increment(bucket, 1L);
117-
// Compute the sum and sum of squires for double values with Kahan summation algorithm
118-
// which is more accurate than naive summation.
119-
compensatedSum.reset(sums.get(bucket), compensations.get(bucket));
120-
compensatedSum.add(value);
121-
sums.set(bucket, compensatedSum.value());
122-
compensations.set(bucket, compensatedSum.delta());
123-
124-
compensatedSum.reset(sumOfSqrs.get(bucket), compensationOfSqrs.get(bucket));
125-
compensatedSum.add(value * value);
126-
sumOfSqrs.set(bucket, compensatedSum.value());
127-
compensationOfSqrs.set(bucket, compensatedSum.delta());
128-
129-
mins.set(bucket, Math.min(mins.get(bucket), value));
130-
maxes.set(bucket, Math.max(maxes.get(bucket), value));
116+
SumAggregator.computeSum(bucket, value, sums, compensations);
117+
SumAggregator.computeSum(bucket, value * value, sumOfSqrs, compensationOfSqrs);
118+
StatsAggregator.updateMinsAndMaxes(bucket, value, mins, maxes);
131119
}
132120
}
133121

@@ -138,13 +126,14 @@ private void maybeGrow(long bucket) {
138126
if (bucket >= counts.size()) {
139127
final long from = counts.size();
140128
final long overSize = BigArrays.overSize(bucket + 1);
141-
counts = bigArrays().resize(counts, overSize);
142-
sums = bigArrays().resize(sums, overSize);
143-
compensations = bigArrays().resize(compensations, overSize);
144-
mins = bigArrays().resize(mins, overSize);
145-
maxes = bigArrays().resize(maxes, overSize);
146-
sumOfSqrs = bigArrays().resize(sumOfSqrs, overSize);
147-
compensationOfSqrs = bigArrays().resize(compensationOfSqrs, overSize);
129+
var bigArrays = bigArrays();
130+
counts = bigArrays.resize(counts, overSize);
131+
sums = bigArrays.resize(sums, overSize);
132+
compensations = bigArrays.resize(compensations, overSize);
133+
mins = bigArrays.resize(mins, overSize);
134+
maxes = bigArrays.resize(maxes, overSize);
135+
sumOfSqrs = bigArrays.resize(sumOfSqrs, overSize);
136+
compensationOfSqrs = bigArrays.resize(compensationOfSqrs, overSize);
148137
mins.fill(from, overSize, Double.POSITIVE_INFINITY);
149138
maxes.fill(from, overSize, Double.NEGATIVE_INFINITY);
150139
}

server/src/main/java/org/elasticsearch/search/aggregations/metrics/GeoCentroidAggregator.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ public void collect(int doc, long bucket) throws IOException {
9393
}
9494

9595
private LeafBucketCollector getLeafCollector(GeoPointValues values, LeafBucketCollector sub) {
96-
final CompensatedSum compensatedSum = new CompensatedSum(0, 0);
9796
return new LeafBucketCollectorBase(sub, values) {
9897
@Override
9998
public void collect(int doc, long bucket) throws IOException {
@@ -104,16 +103,8 @@ public void collect(int doc, long bucket) throws IOException {
104103
// Compute the sum of double values with Kahan summation algorithm which is more
105104
// accurate than naive summation.
106105
final GeoPoint value = values.pointValue();
107-
// latitude
108-
compensatedSum.reset(latSum.get(bucket), latCompensations.get(bucket));
109-
compensatedSum.add(value.getLat());
110-
latSum.set(bucket, compensatedSum.value());
111-
latCompensations.set(bucket, compensatedSum.delta());
112-
// longitude
113-
compensatedSum.reset(lonSum.get(bucket), lonCompensations.get(bucket));
114-
compensatedSum.add(value.getLon());
115-
lonSum.set(bucket, compensatedSum.value());
116-
lonCompensations.set(bucket, compensatedSum.delta());
106+
SumAggregator.computeSum(bucket, value.getLat(), latSum, latCompensations);
107+
SumAggregator.computeSum(bucket, value.getLon(), lonSum, lonCompensations);
117108
}
118109
}
119110
};

server/src/main/java/org/elasticsearch/search/aggregations/metrics/StatsAggregator.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,36 +81,43 @@ public void collect(int doc, long bucket) throws IOException {
8181

8282
@Override
8383
public LeafBucketCollector getLeafCollector(NumericDoubleValues values, LeafBucketCollector sub) {
84-
final CompensatedSum kahanSummation = new CompensatedSum(0, 0);
8584
return new LeafBucketCollectorBase(sub, values) {
8685
@Override
8786
public void collect(int doc, long bucket) throws IOException {
8887
if (values.advanceExact(doc)) {
8988
maybeGrow(bucket);
9089
counts.increment(bucket, 1L);
91-
// Compute the sum of double values with Kahan summation algorithm which is more
92-
// accurate than naive summation.
93-
kahanSummation.reset(sums.get(bucket), compensations.get(bucket));
9490
double value = values.doubleValue();
95-
kahanSummation.add(value);
96-
sums.set(bucket, kahanSummation.value());
97-
compensations.set(bucket, kahanSummation.delta());
98-
mins.set(bucket, Math.min(mins.get(bucket), value));
99-
maxes.set(bucket, Math.max(maxes.get(bucket), value));
91+
SumAggregator.computeSum(bucket, value, sums, compensations);
92+
updateMinsAndMaxes(bucket, value, mins, maxes);
10093
}
10194
}
10295
};
10396
}
10497

98+
static void updateMinsAndMaxes(long bucket, double value, DoubleArray mins, DoubleArray maxes) {
99+
double min = mins.get(bucket);
100+
double updated = Math.min(value, min);
101+
if (updated != min) {
102+
mins.set(bucket, updated);
103+
}
104+
double max = maxes.get(bucket);
105+
updated = Math.max(value, max);
106+
if (updated != max) {
107+
maxes.set(bucket, updated);
108+
}
109+
}
110+
105111
private void maybeGrow(long bucket) {
106112
if (bucket >= counts.size()) {
107113
final long from = counts.size();
108114
final long overSize = BigArrays.overSize(bucket + 1);
109-
counts = bigArrays().resize(counts, overSize);
110-
sums = bigArrays().resize(sums, overSize);
111-
compensations = bigArrays().resize(compensations, overSize);
112-
mins = bigArrays().resize(mins, overSize);
113-
maxes = bigArrays().resize(maxes, overSize);
115+
var bigArrays = bigArrays();
116+
counts = bigArrays.resize(counts, overSize);
117+
sums = bigArrays.resize(sums, overSize);
118+
compensations = bigArrays.resize(compensations, overSize);
119+
mins = bigArrays.resize(mins, overSize);
120+
maxes = bigArrays.resize(maxes, overSize);
114121
mins.fill(from, overSize, Double.POSITIVE_INFINITY);
115122
maxes.fill(from, overSize, Double.NEGATIVE_INFINITY);
116123
}

server/src/main/java/org/elasticsearch/search/aggregations/metrics/SumAggregator.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,15 @@ protected LeafBucketCollector getLeafCollector(NumericDoubleValues values, final
9797
public void collect(int doc, long bucket) throws IOException {
9898
if (values.advanceExact(doc)) {
9999
maybeGrow(bucket);
100-
computeSum(bucket, values, sums, compensations);
100+
computeSum(bucket, values.doubleValue(), sums, compensations);
101101
}
102102
}
103103
};
104104
}
105105

106-
static void computeSum(long bucket, NumericDoubleValues values, DoubleArray sums, DoubleArray compensations) throws IOException {
106+
static void computeSum(long bucket, double added, DoubleArray sums, DoubleArray compensations) {
107107
// Compute the sum of double values with Kahan summation algorithm which is more
108108
// accurate than naive summation.
109-
double added = values.doubleValue();
110109
double value = addIfNonOrInf(added, sums.get(bucket));
111110
if (Double.isFinite(value)) {
112111
double delta = compensations.get(bucket);
@@ -122,8 +121,7 @@ static void computeSum(long bucket, NumericDoubleValues values, DoubleArray sums
122121

123122
protected final void maybeGrow(long bucket) {
124123
if (bucket >= sums.size()) {
125-
var bigArrays = bigArrays();
126-
doGrow(bucket, bigArrays);
124+
doGrow(bucket, bigArrays());
127125
}
128126
}
129127

0 commit comments

Comments
 (0)