Skip to content

Commit a3869f9

Browse files
committed
Make sure range queries are correctly profiled. (#25108)
We introduced a new API for ranges in order to be able to decide whether points or doc values would be more appropriate to execute a query, but since `ProfileWeight` does not implement this API, the optimization is disabled when profiling is enabled.
1 parent 9212cea commit a3869f9

File tree

2 files changed

+118
-4
lines changed

2 files changed

+118
-4
lines changed

core/src/main/java/org/elasticsearch/search/profile/query/ProfileWeight.java

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.lucene.search.Explanation;
2626
import org.apache.lucene.search.Query;
2727
import org.apache.lucene.search.Scorer;
28+
import org.apache.lucene.search.ScorerSupplier;
2829
import org.apache.lucene.search.Weight;
2930
import org.elasticsearch.search.profile.Timer;
3031

@@ -49,19 +50,50 @@ public ProfileWeight(Query query, Weight subQueryWeight, QueryProfileBreakdown p
4950

5051
@Override
5152
public Scorer scorer(LeafReaderContext context) throws IOException {
53+
ScorerSupplier supplier = scorerSupplier(context);
54+
if (supplier == null) {
55+
return null;
56+
}
57+
return supplier.get(false);
58+
}
59+
60+
@Override
61+
public ScorerSupplier scorerSupplier(LeafReaderContext context) throws IOException {
5262
Timer timer = profile.getTimer(QueryTimingType.BUILD_SCORER);
5363
timer.start();
54-
final Scorer subQueryScorer;
64+
final ScorerSupplier subQueryScorerSupplier;
5565
try {
56-
subQueryScorer = subQueryWeight.scorer(context);
66+
subQueryScorerSupplier = subQueryWeight.scorerSupplier(context);
5767
} finally {
5868
timer.stop();
5969
}
60-
if (subQueryScorer == null) {
70+
if (subQueryScorerSupplier == null) {
6171
return null;
6272
}
6373

64-
return new ProfileScorer(this, subQueryScorer, profile);
74+
final ProfileWeight weight = this;
75+
return new ScorerSupplier() {
76+
77+
@Override
78+
public Scorer get(boolean randomAccess) throws IOException {
79+
timer.start();
80+
try {
81+
return new ProfileScorer(weight, subQueryScorerSupplier.get(randomAccess), profile);
82+
} finally {
83+
timer.stop();
84+
}
85+
}
86+
87+
@Override
88+
public long cost() {
89+
timer.start();
90+
try {
91+
return subQueryScorerSupplier.cost();
92+
} finally {
93+
timer.stop();
94+
}
95+
}
96+
};
6597
}
6698

6799
@Override

core/src/test/java/org/elasticsearch/search/profile/query/QueryProfilerTests.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,25 @@
2222
import org.apache.lucene.document.Document;
2323
import org.apache.lucene.document.Field.Store;
2424
import org.apache.lucene.document.StringField;
25+
import org.apache.lucene.index.DirectoryReader;
2526
import org.apache.lucene.index.IndexReader;
27+
import org.apache.lucene.index.IndexWriter;
28+
import org.apache.lucene.index.LeafReaderContext;
2629
import org.apache.lucene.index.RandomIndexWriter;
2730
import org.apache.lucene.index.Term;
31+
import org.apache.lucene.search.ConstantScoreWeight;
32+
import org.apache.lucene.search.DocIdSetIterator;
33+
import org.apache.lucene.search.Explanation;
2834
import org.apache.lucene.search.IndexSearcher;
2935
import org.apache.lucene.search.LeafCollector;
3036
import org.apache.lucene.search.Query;
3137
import org.apache.lucene.search.RandomApproximationQuery;
38+
import org.apache.lucene.search.Scorer;
39+
import org.apache.lucene.search.ScorerSupplier;
3240
import org.apache.lucene.search.Sort;
3341
import org.apache.lucene.search.TermQuery;
3442
import org.apache.lucene.search.TotalHitCountCollector;
43+
import org.apache.lucene.search.Weight;
3544
import org.apache.lucene.store.Directory;
3645
import org.apache.lucene.util.IOUtils;
3746
import org.apache.lucene.util.TestUtil;
@@ -45,6 +54,7 @@
4554
import java.io.IOException;
4655
import java.util.List;
4756
import java.util.Map;
57+
import java.util.Set;
4858

4959
import static org.hamcrest.Matchers.equalTo;
5060
import static org.hamcrest.Matchers.greaterThan;
@@ -191,4 +201,76 @@ public void testCollector() throws IOException {
191201
leafCollector.collect(0);
192202
assertThat(profileCollector.getTime(), greaterThan(time));
193203
}
204+
205+
private static class DummyQuery extends Query {
206+
207+
@Override
208+
public String toString(String field) {
209+
return getClass().getSimpleName();
210+
}
211+
212+
@Override
213+
public boolean equals(Object obj) {
214+
return this == obj;
215+
}
216+
217+
@Override
218+
public int hashCode() {
219+
return 0;
220+
}
221+
222+
@Override
223+
public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
224+
return new ConstantScoreWeight(this) {
225+
@Override
226+
public void extractTerms(Set<Term> terms) {
227+
throw new UnsupportedOperationException();
228+
}
229+
230+
@Override
231+
public Explanation explain(LeafReaderContext context, int doc) throws IOException {
232+
throw new UnsupportedOperationException();
233+
}
234+
235+
@Override
236+
public Scorer scorer(LeafReaderContext context) throws IOException {
237+
throw new UnsupportedOperationException();
238+
}
239+
240+
@Override
241+
public ScorerSupplier scorerSupplier(LeafReaderContext context) throws IOException {
242+
final Weight weight = this;
243+
return new ScorerSupplier() {
244+
245+
@Override
246+
public Scorer get(boolean randomAccess) throws IOException {
247+
throw new UnsupportedOperationException();
248+
}
249+
250+
@Override
251+
public long cost() {
252+
return 42;
253+
}
254+
};
255+
}
256+
};
257+
}
258+
}
259+
260+
public void testScorerSupplier() throws IOException {
261+
Directory dir = newDirectory();
262+
IndexWriter w = new IndexWriter(dir, newIndexWriterConfig());
263+
w.addDocument(new Document());
264+
DirectoryReader reader = DirectoryReader.open(w);
265+
w.close();
266+
IndexSearcher s = newSearcher(reader);
267+
s.setQueryCache(null);
268+
Weight weight = s.createNormalizedWeight(new DummyQuery(), randomBoolean());
269+
// exception when getting the scorer
270+
expectThrows(UnsupportedOperationException.class, () -> weight.scorer(s.getIndexReader().leaves().get(0)));
271+
// no exception, means scorerSupplier is delegated
272+
weight.scorerSupplier(s.getIndexReader().leaves().get(0));
273+
reader.close();
274+
dir.close();
275+
}
194276
}

0 commit comments

Comments
 (0)