Skip to content

Commit 8c83e89

Browse files
author
Hugo Mercier
authored
Merge pull request #29 from opendatasoft/bug/sc-41672/v1-facets-endpoint-is-sometimes-very-slow
Store Rounding.Prepared instead of recomputing it for each value
2 parents 3f38bac + 401d2ba commit 8c83e89

File tree

3 files changed

+32
-19
lines changed

3 files changed

+32
-19
lines changed

src/main/java/org/opendatasoft/elasticsearch/search/aggregations/bucket/DateHierarchyAggregationBuilder.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,28 @@ public IntervalConfig(Rounding.DateTimeUnit dateTimeUnit, String format) {
7575
}
7676
}
7777

78-
public List<RoundingInfo> buildRoundings() {
79-
List<RoundingInfo> roundings = new ArrayList<>();
78+
public static class PreparedRounding {
79+
final RoundingInfo roundingInfo;
80+
final Rounding.Prepared prepared;
81+
82+
public PreparedRounding(RoundingInfo roundingInfo, Rounding.Prepared prepared) {
83+
this.roundingInfo = roundingInfo;
84+
this.prepared = prepared;
85+
}
86+
}
87+
88+
public List<PreparedRounding> buildRoundings() {
89+
List<PreparedRounding> roundings = new ArrayList<>();
8090

8191
ZoneId timeZone = timeZone() == null ? ZoneOffset.UTC: timeZone();
8292

83-
for (String interval: INTERVAL_CONFIG.keySet()) {
84-
roundings.add(new RoundingInfo(interval, createRounding(INTERVAL_CONFIG.get(interval).dateTimeUnit),
93+
long now = System.currentTimeMillis();
94+
for (String interval : INTERVAL_CONFIG.keySet()) {
95+
RoundingInfo ri = new RoundingInfo(interval, createRounding(INTERVAL_CONFIG.get(interval).dateTimeUnit),
8596
new DocValueFormat.DateTime(DateFormatter.forPattern(INTERVAL_CONFIG.get(interval).format), timeZone,
86-
DateFieldMapper.Resolution.MILLISECONDS)));
97+
DateFieldMapper.Resolution.MILLISECONDS));
98+
roundings.add(new PreparedRounding(ri, ri.rounding.prepareForUnknown()));
99+
87100
if (interval.equals(interval())) {
88101
break;
89102
}
@@ -344,13 +357,13 @@ protected ValuesSourceAggregatorFactory innerBuild(AggregationContext context,
344357
Builder subFactoriesBuilder) throws IOException {
345358

346359

347-
final List<RoundingInfo> roundingsInfo = buildRoundings();
360+
final List<PreparedRounding> preparedRoundings = buildRoundings();
348361

349362
return new DateHierarchyAggregatorFactory(
350363
name,
351364
config,
352365
order,
353-
roundingsInfo,
366+
preparedRoundings,
354367
minDocCount,
355368
bucketCountThresholds,
356369
context,

src/main/java/org/opendatasoft/elasticsearch/search/aggregations/bucket/DateHierarchyAggregator.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.apache.lucene.index.SortedNumericDocValues;
55
import org.apache.lucene.util.BytesRef;
66
import org.elasticsearch.ElasticsearchException;
7+
import org.elasticsearch.common.Rounding;
78
import org.elasticsearch.common.io.stream.StreamInput;
89
import org.elasticsearch.common.io.stream.StreamOutput;
910
import org.elasticsearch.common.io.stream.Writeable;
@@ -40,14 +41,14 @@ public DateHierarchyAggregator(String name,
4041
BucketOrder order,
4142
long minDocCount,
4243
BucketCountThresholds bucketCountThresholds,
43-
List<DateHierarchyAggregationBuilder.RoundingInfo> roundingsInfo,
44+
List<DateHierarchyAggregationBuilder.PreparedRounding> preparedRoundings,
4445
Aggregator parent,
4546
CardinalityUpperBound cardinalityUpperBound,
4647
Map<String, Object> metadata
4748
) throws IOException {
4849
super(name, factories, context, parent, cardinalityUpperBound, metadata);
4950
this.valuesSource = valuesSource;
50-
this.roundingsInfo = roundingsInfo;
51+
this.preparedRoundings = preparedRoundings;
5152
this.minDocCount = minDocCount;
5253
bucketOrds = new BytesRefHash(1, context.bigArrays());
5354
this.bucketCountThresholds = bucketCountThresholds;
@@ -143,7 +144,7 @@ public boolean equals(Object obj) {
143144
private final BucketOrder order;
144145
private final long minDocCount;
145146
private final BucketCountThresholds bucketCountThresholds;
146-
private final List<DateHierarchyAggregationBuilder.RoundingInfo> roundingsInfo;
147+
private final List<DateHierarchyAggregationBuilder.PreparedRounding> preparedRoundings;
147148
protected final Comparator<InternalPathHierarchy.InternalBucket> partiallyBuiltBucketComparator;
148149

149150
/**
@@ -158,6 +159,7 @@ public LeafBucketCollector getLeafCollector(LeafReaderContext ctx, LeafBucketCol
158159
return LeafBucketCollector.NO_OP_COLLECTOR;
159160
}
160161
final SortedNumericDocValues values = valuesSource.longValues(ctx);
162+
161163
return new LeafBucketCollectorBase(sub, values) {
162164

163165
@Override
@@ -169,11 +171,9 @@ public void collect(int doc, long bucket) throws IOException {
169171
for (int i = 0; i < valuesCount; ++i) {
170172
long value = values.nextValue();
171173
String path = "";
172-
for (DateHierarchyAggregationBuilder.RoundingInfo roundingInfo: roundingsInfo) {
173-
// A little hacky: Add a microsecond to avoid collision between min dates interval
174-
// Since interval cannot be set to microsecond, it is not a problem
175-
long roundedValue = roundingInfo.rounding.round(value);
176-
path += roundingInfo.format.format(roundedValue).toString();
174+
for (DateHierarchyAggregationBuilder.PreparedRounding preparedRounding: preparedRoundings) {
175+
long roundedValue = preparedRounding.prepared.round(value);
176+
path += preparedRounding.roundingInfo.format.format(roundedValue).toString();
177177
long bucketOrd = bucketOrds.add(new BytesRef(path));
178178
if (bucketOrd < 0) { // already seen
179179
bucketOrd = -1 - bucketOrd;

src/main/java/org/opendatasoft/elasticsearch/search/aggregations/bucket/DateHierarchyAggregatorFactory.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ class DateHierarchyAggregatorFactory extends ValuesSourceAggregatorFactory {
3030

3131
private long minDocCount;
3232
private BucketOrder order;
33-
private List<DateHierarchyAggregationBuilder.RoundingInfo> roundingsInfo;
33+
private List<DateHierarchyAggregationBuilder.PreparedRounding> preparedRoundings;
3434
private final DateHierarchyAggregator.BucketCountThresholds bucketCountThresholds;
3535

3636
DateHierarchyAggregatorFactory(String name,
3737
ValuesSourceConfig config,
3838
BucketOrder order,
39-
List<DateHierarchyAggregationBuilder.RoundingInfo> roundingsInfo,
39+
List<DateHierarchyAggregationBuilder.PreparedRounding> preparedRoundings,
4040
long minDocCount,
4141
DateHierarchyAggregator.BucketCountThresholds bucketCountThresholds,
4242
AggregationContext context,
@@ -46,7 +46,7 @@ class DateHierarchyAggregatorFactory extends ValuesSourceAggregatorFactory {
4646
) throws IOException {
4747
super(name, config, context, parent, subFactoriesBuilder, metadata);
4848
this.order = order;
49-
this.roundingsInfo = roundingsInfo;
49+
this.preparedRoundings = preparedRoundings;
5050
this.minDocCount = minDocCount;
5151
this.bucketCountThresholds = bucketCountThresholds;
5252
}
@@ -99,7 +99,7 @@ protected Aggregator doCreateInternal(Aggregator parent, CardinalityUpperBound c
9999
bucketCountThresholds.ensureValidity();
100100
return new DateHierarchyAggregator(
101101
name, factories, context, (ValuesSource.Numeric) config.getValuesSource(),
102-
order, minDocCount, bucketCountThresholds, roundingsInfo, parent, cardinality, metadata);
102+
order, minDocCount, bucketCountThresholds, preparedRoundings, parent, cardinality, metadata);
103103
}
104104
}
105105

0 commit comments

Comments
 (0)