Refactor of query profile classes to make way for other profile implementations
This commit is contained in:
parent
5a33fdbac7
commit
e37e8af5e2
|
@ -51,7 +51,7 @@ import org.elasticsearch.search.fetch.FetchSearchResultProvider;
|
||||||
import org.elasticsearch.search.internal.InternalSearchHit;
|
import org.elasticsearch.search.internal.InternalSearchHit;
|
||||||
import org.elasticsearch.search.internal.InternalSearchHits;
|
import org.elasticsearch.search.internal.InternalSearchHits;
|
||||||
import org.elasticsearch.search.internal.InternalSearchResponse;
|
import org.elasticsearch.search.internal.InternalSearchResponse;
|
||||||
import org.elasticsearch.search.profile.InternalProfileShardResults;
|
import org.elasticsearch.search.profile.SearchProfileShardResults;
|
||||||
import org.elasticsearch.search.profile.ProfileShardResult;
|
import org.elasticsearch.search.profile.ProfileShardResult;
|
||||||
import org.elasticsearch.search.query.QuerySearchResult;
|
import org.elasticsearch.search.query.QuerySearchResult;
|
||||||
import org.elasticsearch.search.query.QuerySearchResultProvider;
|
import org.elasticsearch.search.query.QuerySearchResultProvider;
|
||||||
|
@ -405,14 +405,14 @@ public class SearchPhaseController extends AbstractComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Collect profile results
|
//Collect profile results
|
||||||
InternalProfileShardResults shardResults = null;
|
SearchProfileShardResults shardResults = null;
|
||||||
if (!queryResults.isEmpty() && firstResult.profileResults() != null) {
|
if (!queryResults.isEmpty() && firstResult.profileResults() != null) {
|
||||||
Map<String, List<ProfileShardResult>> profileResults = new HashMap<>(queryResults.size());
|
Map<String, List<ProfileShardResult>> profileResults = new HashMap<>(queryResults.size());
|
||||||
for (AtomicArray.Entry<? extends QuerySearchResultProvider> entry : queryResults) {
|
for (AtomicArray.Entry<? extends QuerySearchResultProvider> entry : queryResults) {
|
||||||
String key = entry.value.queryResult().shardTarget().toString();
|
String key = entry.value.queryResult().shardTarget().toString();
|
||||||
profileResults.put(key, entry.value.queryResult().profileResults());
|
profileResults.put(key, entry.value.queryResult().profileResults());
|
||||||
}
|
}
|
||||||
shardResults = new InternalProfileShardResults(profileResults);
|
shardResults = new SearchProfileShardResults(profileResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aggregations != null) {
|
if (aggregations != null) {
|
||||||
|
|
|
@ -33,9 +33,10 @@ import org.apache.lucene.search.Weight;
|
||||||
import org.elasticsearch.common.lease.Releasable;
|
import org.elasticsearch.common.lease.Releasable;
|
||||||
import org.elasticsearch.index.engine.Engine;
|
import org.elasticsearch.index.engine.Engine;
|
||||||
import org.elasticsearch.search.dfs.AggregatedDfs;
|
import org.elasticsearch.search.dfs.AggregatedDfs;
|
||||||
import org.elasticsearch.search.profile.ProfileBreakdown;
|
import org.elasticsearch.search.profile.QueryProfileBreakdown;
|
||||||
import org.elasticsearch.search.profile.ProfileWeight;
|
import org.elasticsearch.search.profile.ProfileWeight;
|
||||||
import org.elasticsearch.search.profile.Profiler;
|
import org.elasticsearch.search.profile.QueryProfiler;
|
||||||
|
import org.elasticsearch.search.profile.QueryTimingType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||||
private final Engine.Searcher engineSearcher;
|
private final Engine.Searcher engineSearcher;
|
||||||
|
|
||||||
// TODO revisit moving the profiler to inheritance or wrapping model in the future
|
// TODO revisit moving the profiler to inheritance or wrapping model in the future
|
||||||
private Profiler profiler;
|
private QueryProfiler profiler;
|
||||||
|
|
||||||
public ContextIndexSearcher(Engine.Searcher searcher,
|
public ContextIndexSearcher(Engine.Searcher searcher,
|
||||||
QueryCache queryCache, QueryCachingPolicy queryCachingPolicy) {
|
QueryCache queryCache, QueryCachingPolicy queryCachingPolicy) {
|
||||||
|
@ -70,7 +71,7 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||||
public void close() {
|
public void close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProfiler(Profiler profiler) {
|
public void setProfiler(QueryProfiler profiler) {
|
||||||
this.profiler = profiler;
|
this.profiler = profiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,8 +115,8 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||||
// createWeight() is called for each query in the tree, so we tell the queryProfiler
|
// createWeight() is called for each query in the tree, so we tell the queryProfiler
|
||||||
// each invocation so that it can build an internal representation of the query
|
// each invocation so that it can build an internal representation of the query
|
||||||
// tree
|
// tree
|
||||||
ProfileBreakdown profile = profiler.getQueryBreakdown(query);
|
QueryProfileBreakdown profile = profiler.getQueryBreakdown(query);
|
||||||
profile.startTime(ProfileBreakdown.TimingType.CREATE_WEIGHT);
|
profile.startTime(QueryTimingType.CREATE_WEIGHT);
|
||||||
final Weight weight;
|
final Weight weight;
|
||||||
try {
|
try {
|
||||||
weight = super.createWeight(query, needsScores);
|
weight = super.createWeight(query, needsScores);
|
||||||
|
|
|
@ -28,7 +28,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.search.SearchHits;
|
import org.elasticsearch.search.SearchHits;
|
||||||
import org.elasticsearch.search.aggregations.Aggregations;
|
import org.elasticsearch.search.aggregations.Aggregations;
|
||||||
import org.elasticsearch.search.aggregations.InternalAggregations;
|
import org.elasticsearch.search.aggregations.InternalAggregations;
|
||||||
import org.elasticsearch.search.profile.InternalProfileShardResults;
|
import org.elasticsearch.search.profile.SearchProfileShardResults;
|
||||||
import org.elasticsearch.search.profile.ProfileShardResult;
|
import org.elasticsearch.search.profile.ProfileShardResult;
|
||||||
import org.elasticsearch.search.suggest.Suggest;
|
import org.elasticsearch.search.suggest.Suggest;
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ public class InternalSearchResponse implements Streamable, ToXContent {
|
||||||
|
|
||||||
private Suggest suggest;
|
private Suggest suggest;
|
||||||
|
|
||||||
private InternalProfileShardResults profileResults;
|
private SearchProfileShardResults profileResults;
|
||||||
|
|
||||||
private boolean timedOut;
|
private boolean timedOut;
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ public class InternalSearchResponse implements Streamable, ToXContent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public InternalSearchResponse(InternalSearchHits hits, InternalAggregations aggregations, Suggest suggest,
|
public InternalSearchResponse(InternalSearchHits hits, InternalAggregations aggregations, Suggest suggest,
|
||||||
InternalProfileShardResults profileResults, boolean timedOut, Boolean terminatedEarly) {
|
SearchProfileShardResults profileResults, boolean timedOut, Boolean terminatedEarly) {
|
||||||
this.hits = hits;
|
this.hits = hits;
|
||||||
this.aggregations = aggregations;
|
this.aggregations = aggregations;
|
||||||
this.suggest = suggest;
|
this.suggest = suggest;
|
||||||
|
@ -141,7 +141,7 @@ public class InternalSearchResponse implements Streamable, ToXContent {
|
||||||
terminatedEarly = in.readOptionalBoolean();
|
terminatedEarly = in.readOptionalBoolean();
|
||||||
|
|
||||||
if (in.getVersion().onOrAfter(Version.V_2_2_0) && in.readBoolean()) {
|
if (in.getVersion().onOrAfter(Version.V_2_2_0) && in.readBoolean()) {
|
||||||
profileResults = new InternalProfileShardResults(in);
|
profileResults = new SearchProfileShardResults(in);
|
||||||
} else {
|
} else {
|
||||||
profileResults = null;
|
profileResults = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ package org.elasticsearch.search.profile;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,22 +28,7 @@ import java.util.Map;
|
||||||
* A node's time may be composed of several internal attributes (rewriting, weighting,
|
* A node's time may be composed of several internal attributes (rewriting, weighting,
|
||||||
* scoring, etc).
|
* scoring, etc).
|
||||||
*/
|
*/
|
||||||
public final class ProfileBreakdown {
|
public abstract class AbstractProfileBreakdown<T extends Enum<T>> {
|
||||||
|
|
||||||
/** Enumeration of all supported timing types. */
|
|
||||||
public enum TimingType {
|
|
||||||
CREATE_WEIGHT,
|
|
||||||
BUILD_SCORER,
|
|
||||||
NEXT_DOC,
|
|
||||||
ADVANCE,
|
|
||||||
MATCH,
|
|
||||||
SCORE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name().toLowerCase(Locale.ROOT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accumulated timings for this query node
|
* The accumulated timings for this query node
|
||||||
|
@ -52,23 +36,26 @@ public final class ProfileBreakdown {
|
||||||
private final long[] timings;
|
private final long[] timings;
|
||||||
|
|
||||||
/** Scratch to store the current timing type. */
|
/** Scratch to store the current timing type. */
|
||||||
private TimingType currentTimingType;
|
private T currentTimingType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The temporary scratch space for holding start-times
|
* The temporary scratch space for holding start-times
|
||||||
*/
|
*/
|
||||||
private long scratch;
|
private long scratch;
|
||||||
|
|
||||||
|
private T[] timingTypes;
|
||||||
|
|
||||||
/** Sole constructor. */
|
/** Sole constructor. */
|
||||||
public ProfileBreakdown() {
|
public AbstractProfileBreakdown(T[] timingTypes) {
|
||||||
timings = new long[TimingType.values().length];
|
this.timingTypes = timingTypes;
|
||||||
|
timings = new long[timingTypes.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin timing a query for a specific Timing context
|
* Begin timing a query for a specific Timing context
|
||||||
* @param timing The timing context being profiled
|
* @param timing The timing context being profiled
|
||||||
*/
|
*/
|
||||||
public void startTime(TimingType timing) {
|
public void startTime(T timing) {
|
||||||
assert currentTimingType == null;
|
assert currentTimingType == null;
|
||||||
assert scratch == 0;
|
assert scratch == 0;
|
||||||
currentTimingType = timing;
|
currentTimingType = timing;
|
||||||
|
@ -91,10 +78,10 @@ public final class ProfileBreakdown {
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert this record to a map from {@link TimingType} to times. */
|
/** Convert this record to a map from timingType to times. */
|
||||||
public Map<String, Long> toTimingMap() {
|
public Map<String, Long> toTimingMap() {
|
||||||
Map<String, Long> map = new HashMap<>();
|
Map<String, Long> map = new HashMap<>();
|
||||||
for (TimingType timingType : TimingType.values()) {
|
for (T timingType : timingTypes) {
|
||||||
map.put(timingType.toString(), timings[timingType.ordinal()]);
|
map.put(timingType.toString(), timings[timingType.ordinal()]);
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableMap(map);
|
return Collections.unmodifiableMap(map);
|
||||||
|
@ -104,7 +91,7 @@ public final class ProfileBreakdown {
|
||||||
* Add <code>other</code>'s timings into this breakdown
|
* Add <code>other</code>'s timings into this breakdown
|
||||||
* @param other Another Breakdown to merge with this one
|
* @param other Another Breakdown to merge with this one
|
||||||
*/
|
*/
|
||||||
public void merge(ProfileBreakdown other) {
|
public void merge(AbstractProfileBreakdown<T> other) {
|
||||||
assert(timings.length == other.timings.length);
|
assert(timings.length == other.timings.length);
|
||||||
for (int i = 0; i < timings.length; ++i) {
|
for (int i = 0; i < timings.length; ++i) {
|
||||||
timings[i] += other.timings[i];
|
timings[i] += other.timings[i];
|
|
@ -30,12 +30,12 @@ import java.util.concurrent.LinkedBlockingDeque;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class tracks the dependency tree for queries (scoring and rewriting) and
|
* This class tracks the dependency tree for queries (scoring and rewriting) and
|
||||||
* generates {@link ProfileBreakdown} for each node in the tree. It also finalizes the tree
|
* generates {@link QueryProfileBreakdown} for each node in the tree. It also finalizes the tree
|
||||||
* and returns a list of {@link ProfileResult} that can be serialized back to the client
|
* and returns a list of {@link ProfileResult} that can be serialized back to the client
|
||||||
*/
|
*/
|
||||||
final class InternalProfileTree {
|
final class InternalQueryProfileTree {
|
||||||
|
|
||||||
private ArrayList<ProfileBreakdown> timings;
|
private ArrayList<QueryProfileBreakdown> timings;
|
||||||
|
|
||||||
/** Maps the Query to it's list of children. This is basically the dependency tree */
|
/** Maps the Query to it's list of children. This is basically the dependency tree */
|
||||||
private ArrayList<ArrayList<Integer>> tree;
|
private ArrayList<ArrayList<Integer>> tree;
|
||||||
|
@ -55,7 +55,7 @@ final class InternalProfileTree {
|
||||||
|
|
||||||
private int currentToken = 0;
|
private int currentToken = 0;
|
||||||
|
|
||||||
public InternalProfileTree() {
|
public InternalQueryProfileTree() {
|
||||||
timings = new ArrayList<>(10);
|
timings = new ArrayList<>(10);
|
||||||
stack = new LinkedBlockingDeque<>(10);
|
stack = new LinkedBlockingDeque<>(10);
|
||||||
tree = new ArrayList<>(10);
|
tree = new ArrayList<>(10);
|
||||||
|
@ -64,7 +64,7 @@ final class InternalProfileTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link ProfileBreakdown} for a scoring query. Scoring queries (e.g. those
|
* Returns a {@link QueryProfileBreakdown} for a scoring query. Scoring queries (e.g. those
|
||||||
* that are past the rewrite phase and are now being wrapped by createWeight() ) follow
|
* that are past the rewrite phase and are now being wrapped by createWeight() ) follow
|
||||||
* a recursive progression. We can track the dependency tree by a simple stack
|
* a recursive progression. We can track the dependency tree by a simple stack
|
||||||
*
|
*
|
||||||
|
@ -74,7 +74,7 @@ final class InternalProfileTree {
|
||||||
* @param query The scoring query we wish to profile
|
* @param query The scoring query we wish to profile
|
||||||
* @return A ProfileBreakdown for this query
|
* @return A ProfileBreakdown for this query
|
||||||
*/
|
*/
|
||||||
public ProfileBreakdown getQueryBreakdown(Query query) {
|
public QueryProfileBreakdown getQueryBreakdown(Query query) {
|
||||||
int token = currentToken;
|
int token = currentToken;
|
||||||
|
|
||||||
boolean stackEmpty = stack.isEmpty();
|
boolean stackEmpty = stack.isEmpty();
|
||||||
|
@ -131,14 +131,14 @@ final class InternalProfileTree {
|
||||||
* Helper method to add a new node to the dependency tree.
|
* Helper method to add a new node to the dependency tree.
|
||||||
*
|
*
|
||||||
* Initializes a new list in the dependency tree, saves the query and
|
* Initializes a new list in the dependency tree, saves the query and
|
||||||
* generates a new {@link ProfileBreakdown} to track the timings
|
* generates a new {@link QueryProfileBreakdown} to track the timings
|
||||||
* of this query
|
* of this query
|
||||||
*
|
*
|
||||||
* @param query The query to profile
|
* @param query The query to profile
|
||||||
* @param token The assigned token for this query
|
* @param token The assigned token for this query
|
||||||
* @return A ProfileBreakdown to profile this query
|
* @return A ProfileBreakdown to profile this query
|
||||||
*/
|
*/
|
||||||
private ProfileBreakdown addDependencyNode(Query query, int token) {
|
private QueryProfileBreakdown addDependencyNode(Query query, int token) {
|
||||||
|
|
||||||
// Add a new slot in the dependency tree
|
// Add a new slot in the dependency tree
|
||||||
tree.add(new ArrayList<>(5));
|
tree.add(new ArrayList<>(5));
|
||||||
|
@ -146,7 +146,7 @@ final class InternalProfileTree {
|
||||||
// Save our query for lookup later
|
// Save our query for lookup later
|
||||||
queries.add(query);
|
queries.add(query);
|
||||||
|
|
||||||
ProfileBreakdown queryTimings = new ProfileBreakdown();
|
QueryProfileBreakdown queryTimings = new QueryProfileBreakdown();
|
||||||
timings.add(token, queryTimings);
|
timings.add(token, queryTimings);
|
||||||
return queryTimings;
|
return queryTimings;
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ final class InternalProfileTree {
|
||||||
*/
|
*/
|
||||||
private ProfileResult doGetQueryTree(int token) {
|
private ProfileResult doGetQueryTree(int token) {
|
||||||
Query query = queries.get(token);
|
Query query = queries.get(token);
|
||||||
ProfileBreakdown breakdown = timings.get(token);
|
QueryProfileBreakdown breakdown = timings.get(token);
|
||||||
Map<String, Long> timings = breakdown.toTimingMap();
|
Map<String, Long> timings = breakdown.toTimingMap();
|
||||||
List<Integer> children = tree.get(token);
|
List<Integer> children = tree.get(token);
|
||||||
List<ProfileResult> childrenProfileResults = Collections.emptyList();
|
List<ProfileResult> childrenProfileResults = Collections.emptyList();
|
|
@ -45,22 +45,22 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
final class ProfileResult implements Writeable, ToXContent {
|
final class ProfileResult implements Writeable, ToXContent {
|
||||||
|
|
||||||
private static final ParseField QUERY_TYPE = new ParseField("query_type");
|
private static final ParseField TYPE = new ParseField("type");
|
||||||
private static final ParseField LUCENE_DESCRIPTION = new ParseField("lucene");
|
private static final ParseField DESCRIPTION = new ParseField("description");
|
||||||
private static final ParseField NODE_TIME = new ParseField("time");
|
private static final ParseField NODE_TIME = new ParseField("time");
|
||||||
private static final ParseField CHILDREN = new ParseField("children");
|
private static final ParseField CHILDREN = new ParseField("children");
|
||||||
private static final ParseField BREAKDOWN = new ParseField("breakdown");
|
private static final ParseField BREAKDOWN = new ParseField("breakdown");
|
||||||
|
|
||||||
private final String queryType;
|
private final String type;
|
||||||
private final String luceneDescription;
|
private final String description;
|
||||||
private final Map<String, Long> timings;
|
private final Map<String, Long> timings;
|
||||||
private final long nodeTime;
|
private final long nodeTime;
|
||||||
private final List<ProfileResult> children;
|
private final List<ProfileResult> children;
|
||||||
|
|
||||||
public ProfileResult(String queryType, String luceneDescription, Map<String, Long> timings, List<ProfileResult> children,
|
public ProfileResult(String type, String description, Map<String, Long> timings, List<ProfileResult> children,
|
||||||
long nodeTime) {
|
long nodeTime) {
|
||||||
this.queryType = queryType;
|
this.type = type;
|
||||||
this.luceneDescription = luceneDescription;
|
this.description = description;
|
||||||
this.timings = timings;
|
this.timings = timings;
|
||||||
this.children = children;
|
this.children = children;
|
||||||
this.nodeTime = nodeTime;
|
this.nodeTime = nodeTime;
|
||||||
|
@ -70,8 +70,8 @@ final class ProfileResult implements Writeable, ToXContent {
|
||||||
* Read from a stream.
|
* Read from a stream.
|
||||||
*/
|
*/
|
||||||
public ProfileResult(StreamInput in) throws IOException{
|
public ProfileResult(StreamInput in) throws IOException{
|
||||||
this.queryType = in.readString();
|
this.type = in.readString();
|
||||||
this.luceneDescription = in.readString();
|
this.description = in.readString();
|
||||||
this.nodeTime = in.readLong();
|
this.nodeTime = in.readLong();
|
||||||
|
|
||||||
int timingsSize = in.readVInt();
|
int timingsSize = in.readVInt();
|
||||||
|
@ -90,8 +90,8 @@ final class ProfileResult implements Writeable, ToXContent {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(StreamOutput out) throws IOException {
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
out.writeString(queryType);
|
out.writeString(type);
|
||||||
out.writeString(luceneDescription);
|
out.writeString(description);
|
||||||
out.writeLong(nodeTime); // not Vlong because can be negative
|
out.writeLong(nodeTime); // not Vlong because can be negative
|
||||||
out.writeVInt(timings.size());
|
out.writeVInt(timings.size());
|
||||||
for (Map.Entry<String, Long> entry : timings.entrySet()) {
|
for (Map.Entry<String, Long> entry : timings.entrySet()) {
|
||||||
|
@ -108,14 +108,14 @@ final class ProfileResult implements Writeable, ToXContent {
|
||||||
* Retrieve the lucene description of this query (e.g. the "explain" text)
|
* Retrieve the lucene description of this query (e.g. the "explain" text)
|
||||||
*/
|
*/
|
||||||
public String getLuceneDescription() {
|
public String getLuceneDescription() {
|
||||||
return luceneDescription;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the name of the query (e.g. "TermQuery")
|
* Retrieve the name of the query (e.g. "TermQuery")
|
||||||
*/
|
*/
|
||||||
public String getQueryName() {
|
public String getQueryName() {
|
||||||
return queryType;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,9 +144,9 @@ final class ProfileResult implements Writeable, ToXContent {
|
||||||
@Override
|
@Override
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
builder = builder.startObject()
|
builder = builder.startObject()
|
||||||
.field(QUERY_TYPE.getPreferredName(), queryType)
|
.field(TYPE.getPreferredName(), type)
|
||||||
.field(LUCENE_DESCRIPTION.getPreferredName(), luceneDescription)
|
.field(DESCRIPTION.getPreferredName(), description)
|
||||||
.field(NODE_TIME.getPreferredName(), String.format(Locale.US, "%.10gms", (double)(getTime() / 1000000.0)))
|
.field(NODE_TIME.getPreferredName(), String.format(Locale.US, "%.10gms", getTime() / 1000000.0))
|
||||||
.field(BREAKDOWN.getPreferredName(), timings);
|
.field(BREAKDOWN.getPreferredName(), timings);
|
||||||
|
|
||||||
if (!children.isEmpty()) {
|
if (!children.isEmpty()) {
|
||||||
|
|
|
@ -35,9 +35,9 @@ final class ProfileScorer extends Scorer {
|
||||||
|
|
||||||
private final Scorer scorer;
|
private final Scorer scorer;
|
||||||
private ProfileWeight profileWeight;
|
private ProfileWeight profileWeight;
|
||||||
private final ProfileBreakdown profile;
|
private final QueryProfileBreakdown profile;
|
||||||
|
|
||||||
ProfileScorer(ProfileWeight w, Scorer scorer, ProfileBreakdown profile) throws IOException {
|
ProfileScorer(ProfileWeight w, Scorer scorer, QueryProfileBreakdown profile) throws IOException {
|
||||||
super(w);
|
super(w);
|
||||||
this.scorer = scorer;
|
this.scorer = scorer;
|
||||||
this.profileWeight = w;
|
this.profileWeight = w;
|
||||||
|
@ -51,7 +51,7 @@ final class ProfileScorer extends Scorer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float score() throws IOException {
|
public float score() throws IOException {
|
||||||
profile.startTime(ProfileBreakdown.TimingType.SCORE);
|
profile.startTime(QueryTimingType.SCORE);
|
||||||
try {
|
try {
|
||||||
return scorer.score();
|
return scorer.score();
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -81,7 +81,7 @@ final class ProfileScorer extends Scorer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int advance(int target) throws IOException {
|
public int advance(int target) throws IOException {
|
||||||
profile.startTime(ProfileBreakdown.TimingType.ADVANCE);
|
profile.startTime(QueryTimingType.ADVANCE);
|
||||||
try {
|
try {
|
||||||
return in.advance(target);
|
return in.advance(target);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -91,7 +91,7 @@ final class ProfileScorer extends Scorer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int nextDoc() throws IOException {
|
public int nextDoc() throws IOException {
|
||||||
profile.startTime(ProfileBreakdown.TimingType.NEXT_DOC);
|
profile.startTime(QueryTimingType.NEXT_DOC);
|
||||||
try {
|
try {
|
||||||
return in.nextDoc();
|
return in.nextDoc();
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -122,7 +122,7 @@ final class ProfileScorer extends Scorer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int advance(int target) throws IOException {
|
public int advance(int target) throws IOException {
|
||||||
profile.startTime(ProfileBreakdown.TimingType.ADVANCE);
|
profile.startTime(QueryTimingType.ADVANCE);
|
||||||
try {
|
try {
|
||||||
return inApproximation.advance(target);
|
return inApproximation.advance(target);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -132,7 +132,7 @@ final class ProfileScorer extends Scorer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int nextDoc() throws IOException {
|
public int nextDoc() throws IOException {
|
||||||
profile.startTime(ProfileBreakdown.TimingType.NEXT_DOC);
|
profile.startTime(QueryTimingType.NEXT_DOC);
|
||||||
try {
|
try {
|
||||||
return inApproximation.nextDoc();
|
return inApproximation.nextDoc();
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -153,7 +153,7 @@ final class ProfileScorer extends Scorer {
|
||||||
return new TwoPhaseIterator(approximation) {
|
return new TwoPhaseIterator(approximation) {
|
||||||
@Override
|
@Override
|
||||||
public boolean matches() throws IOException {
|
public boolean matches() throws IOException {
|
||||||
profile.startTime(ProfileBreakdown.TimingType.MATCH);
|
profile.startTime(QueryTimingType.MATCH);
|
||||||
try {
|
try {
|
||||||
return in.matches();
|
return in.matches();
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -36,16 +36,16 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public final class ProfileShardResult implements Writeable, ToXContent {
|
public final class ProfileShardResult implements Writeable, ToXContent {
|
||||||
|
|
||||||
private final List<ProfileResult> profileResults;
|
private final List<ProfileResult> queryProfileResults;
|
||||||
|
|
||||||
private final CollectorResult profileCollector;
|
private final CollectorResult profileCollector;
|
||||||
|
|
||||||
private final long rewriteTime;
|
private final long rewriteTime;
|
||||||
|
|
||||||
public ProfileShardResult(List<ProfileResult> profileResults, long rewriteTime,
|
public ProfileShardResult(List<ProfileResult> queryProfileResults, long rewriteTime,
|
||||||
CollectorResult profileCollector) {
|
CollectorResult profileCollector) {
|
||||||
assert(profileCollector != null);
|
assert(profileCollector != null);
|
||||||
this.profileResults = profileResults;
|
this.queryProfileResults = queryProfileResults;
|
||||||
this.profileCollector = profileCollector;
|
this.profileCollector = profileCollector;
|
||||||
this.rewriteTime = rewriteTime;
|
this.rewriteTime = rewriteTime;
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,9 @@ public final class ProfileShardResult implements Writeable, ToXContent {
|
||||||
*/
|
*/
|
||||||
public ProfileShardResult(StreamInput in) throws IOException {
|
public ProfileShardResult(StreamInput in) throws IOException {
|
||||||
int profileSize = in.readVInt();
|
int profileSize = in.readVInt();
|
||||||
profileResults = new ArrayList<>(profileSize);
|
queryProfileResults = new ArrayList<>(profileSize);
|
||||||
for (int j = 0; j < profileSize; j++) {
|
for (int j = 0; j < profileSize; j++) {
|
||||||
profileResults.add(new ProfileResult(in));
|
queryProfileResults.add(new ProfileResult(in));
|
||||||
}
|
}
|
||||||
|
|
||||||
profileCollector = new CollectorResult(in);
|
profileCollector = new CollectorResult(in);
|
||||||
|
@ -66,8 +66,8 @@ public final class ProfileShardResult implements Writeable, ToXContent {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(StreamOutput out) throws IOException {
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
out.writeVInt(profileResults.size());
|
out.writeVInt(queryProfileResults.size());
|
||||||
for (ProfileResult p : profileResults) {
|
for (ProfileResult p : queryProfileResults) {
|
||||||
p.writeTo(out);
|
p.writeTo(out);
|
||||||
}
|
}
|
||||||
profileCollector.writeTo(out);
|
profileCollector.writeTo(out);
|
||||||
|
@ -76,7 +76,7 @@ public final class ProfileShardResult implements Writeable, ToXContent {
|
||||||
|
|
||||||
|
|
||||||
public List<ProfileResult> getQueryResults() {
|
public List<ProfileResult> getQueryResults() {
|
||||||
return Collections.unmodifiableList(profileResults);
|
return Collections.unmodifiableList(queryProfileResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getRewriteTime() {
|
public long getRewriteTime() {
|
||||||
|
@ -90,7 +90,7 @@ public final class ProfileShardResult implements Writeable, ToXContent {
|
||||||
@Override
|
@Override
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
builder.startArray("query");
|
builder.startArray("query");
|
||||||
for (ProfileResult p : profileResults) {
|
for (ProfileResult p : queryProfileResults) {
|
||||||
p.toXContent(builder, params);
|
p.toXContent(builder, params);
|
||||||
}
|
}
|
||||||
builder.endArray();
|
builder.endArray();
|
||||||
|
|
|
@ -38,9 +38,9 @@ import java.util.Set;
|
||||||
public final class ProfileWeight extends Weight {
|
public final class ProfileWeight extends Weight {
|
||||||
|
|
||||||
private final Weight subQueryWeight;
|
private final Weight subQueryWeight;
|
||||||
private final ProfileBreakdown profile;
|
private final QueryProfileBreakdown profile;
|
||||||
|
|
||||||
public ProfileWeight(Query query, Weight subQueryWeight, ProfileBreakdown profile) throws IOException {
|
public ProfileWeight(Query query, Weight subQueryWeight, QueryProfileBreakdown profile) throws IOException {
|
||||||
super(query);
|
super(query);
|
||||||
this.subQueryWeight = subQueryWeight;
|
this.subQueryWeight = subQueryWeight;
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
|
@ -48,7 +48,7 @@ public final class ProfileWeight extends Weight {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Scorer scorer(LeafReaderContext context) throws IOException {
|
public Scorer scorer(LeafReaderContext context) throws IOException {
|
||||||
profile.startTime(ProfileBreakdown.TimingType.BUILD_SCORER);
|
profile.startTime(QueryTimingType.BUILD_SCORER);
|
||||||
final Scorer subQueryScorer;
|
final Scorer subQueryScorer;
|
||||||
try {
|
try {
|
||||||
subQueryScorer = subQueryWeight.scorer(context);
|
subQueryScorer = subQueryWeight.scorer(context);
|
||||||
|
|
|
@ -25,13 +25,13 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Wrapper around several {@link Profiler}s that makes management easier. */
|
/** Wrapper around several {@link QueryProfiler}s that makes management easier. */
|
||||||
public final class Profilers {
|
public final class Profilers {
|
||||||
|
|
||||||
private final ContextIndexSearcher searcher;
|
private final ContextIndexSearcher searcher;
|
||||||
private final List<Profiler> profilers;
|
private final List<QueryProfiler> profilers;
|
||||||
|
|
||||||
/** Sole constructor. This {@link Profilers} instance will initially wrap one {@link Profiler}. */
|
/** Sole constructor. This {@link Profilers} instance will initially wrap one {@link QueryProfiler}. */
|
||||||
public Profilers(ContextIndexSearcher searcher) {
|
public Profilers(ContextIndexSearcher searcher) {
|
||||||
this.searcher = searcher;
|
this.searcher = searcher;
|
||||||
this.profilers = new ArrayList<>();
|
this.profilers = new ArrayList<>();
|
||||||
|
@ -39,20 +39,20 @@ public final class Profilers {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Switch to a new profile. */
|
/** Switch to a new profile. */
|
||||||
public Profiler addProfiler() {
|
public QueryProfiler addProfiler() {
|
||||||
Profiler profiler = new Profiler();
|
QueryProfiler profiler = new QueryProfiler();
|
||||||
searcher.setProfiler(profiler);
|
searcher.setProfiler(profiler);
|
||||||
profilers.add(profiler);
|
profilers.add(profiler);
|
||||||
return profiler;
|
return profiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the current profiler. */
|
/** Get the current profiler. */
|
||||||
public Profiler getCurrent() {
|
public QueryProfiler getCurrent() {
|
||||||
return profilers.get(profilers.size() - 1);
|
return profilers.get(profilers.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the list of all created {@link Profiler}s so far. */
|
/** Return the list of all created {@link QueryProfiler}s so far. */
|
||||||
public List<Profiler> getProfilers() {
|
public List<QueryProfiler> getProfilers() {
|
||||||
return Collections.unmodifiableList(profilers);
|
return Collections.unmodifiableList(profilers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.search.profile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A record of timings for the various operations that may happen during query execution.
|
||||||
|
* A node's time may be composed of several internal attributes (rewriting, weighting,
|
||||||
|
* scoring, etc).
|
||||||
|
*/
|
||||||
|
public final class QueryProfileBreakdown extends AbstractProfileBreakdown<QueryTimingType> {
|
||||||
|
|
||||||
|
/** Sole constructor. */
|
||||||
|
public QueryProfileBreakdown() {
|
||||||
|
super(QueryTimingType.values());
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,6 @@ package org.elasticsearch.search.profile;
|
||||||
|
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -36,16 +35,16 @@ import java.util.Objects;
|
||||||
* request may execute two searches (query + global agg). A Profiler just
|
* request may execute two searches (query + global agg). A Profiler just
|
||||||
* represents one of those
|
* represents one of those
|
||||||
*/
|
*/
|
||||||
public final class Profiler {
|
public final class QueryProfiler {
|
||||||
|
|
||||||
private final InternalProfileTree queryTree = new InternalProfileTree();
|
private final InternalQueryProfileTree queryTree = new InternalQueryProfileTree();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The root Collector used in the search
|
* The root Collector used in the search
|
||||||
*/
|
*/
|
||||||
private InternalProfileCollector collector;
|
private InternalProfileCollector collector;
|
||||||
|
|
||||||
public Profiler() {}
|
public QueryProfiler() {}
|
||||||
|
|
||||||
/** Set the collector that is associated with this profiler. */
|
/** Set the collector that is associated with this profiler. */
|
||||||
public void setCollector(InternalProfileCollector collector) {
|
public void setCollector(InternalProfileCollector collector) {
|
||||||
|
@ -56,11 +55,11 @@ public final class Profiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link ProfileBreakdown} for the given query, potentially creating it if it did not exist.
|
* Get the {@link QueryProfileBreakdown} for the given query, potentially creating it if it did not exist.
|
||||||
* This should only be used for queries that will be undergoing scoring. Do not use it to profile the
|
* This should only be used for queries that will be undergoing scoring. Do not use it to profile the
|
||||||
* rewriting phase
|
* rewriting phase
|
||||||
*/
|
*/
|
||||||
public ProfileBreakdown getQueryBreakdown(Query query) {
|
public QueryProfileBreakdown getQueryBreakdown(Query query) {
|
||||||
return queryTree.getQueryBreakdown(query);
|
return queryTree.getQueryBreakdown(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,22 +110,5 @@ public final class Profiler {
|
||||||
return collector.getCollectorTree();
|
return collector.getCollectorTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to convert Profiler into InternalProfileShardResults, which can be
|
|
||||||
* serialized to other nodes, emitted as JSON, etc.
|
|
||||||
*
|
|
||||||
* @param profilers A list of Profilers to convert into InternalProfileShardResults
|
|
||||||
* @return A list of corresponding InternalProfileShardResults
|
|
||||||
*/
|
|
||||||
public static List<ProfileShardResult> buildShardResults(List<Profiler> profilers) {
|
|
||||||
List<ProfileShardResult> results = new ArrayList<>(profilers.size());
|
|
||||||
for (Profiler profiler : profilers) {
|
|
||||||
ProfileShardResult result = new ProfileShardResult(
|
|
||||||
profiler.getQueryTree(), profiler.getRewriteTime(), profiler.getCollector());
|
|
||||||
results.add(result);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.search.profile;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public enum QueryTimingType {
|
||||||
|
CREATE_WEIGHT,
|
||||||
|
BUILD_SCORER,
|
||||||
|
NEXT_DOC,
|
||||||
|
ADVANCE,
|
||||||
|
MATCH,
|
||||||
|
SCORE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name().toLowerCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,11 +37,11 @@ import java.util.stream.Collectors;
|
||||||
* A container class to hold all the profile results across all shards. Internally
|
* A container class to hold all the profile results across all shards. Internally
|
||||||
* holds a map of shard ID -> Profiled results
|
* holds a map of shard ID -> Profiled results
|
||||||
*/
|
*/
|
||||||
public final class InternalProfileShardResults implements Writeable, ToXContent{
|
public final class SearchProfileShardResults implements Writeable, ToXContent{
|
||||||
|
|
||||||
private Map<String, List<ProfileShardResult>> shardResults;
|
private Map<String, List<ProfileShardResult>> shardResults;
|
||||||
|
|
||||||
public InternalProfileShardResults(Map<String, List<ProfileShardResult>> shardResults) {
|
public SearchProfileShardResults(Map<String, List<ProfileShardResult>> shardResults) {
|
||||||
Map<String, List<ProfileShardResult>> transformed =
|
Map<String, List<ProfileShardResult>> transformed =
|
||||||
shardResults.entrySet()
|
shardResults.entrySet()
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -52,7 +52,7 @@ public final class InternalProfileShardResults implements Writeable, ToXContent{
|
||||||
this.shardResults = Collections.unmodifiableMap(transformed);
|
this.shardResults = Collections.unmodifiableMap(transformed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InternalProfileShardResults(StreamInput in) throws IOException {
|
public SearchProfileShardResults(StreamInput in) throws IOException {
|
||||||
int size = in.readInt();
|
int size = in.readInt();
|
||||||
shardResults = new HashMap<>(size);
|
shardResults = new HashMap<>(size);
|
||||||
|
|
||||||
|
@ -105,4 +105,22 @@ public final class InternalProfileShardResults implements Writeable, ToXContent{
|
||||||
builder.endArray().endObject();
|
builder.endArray().endObject();
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to convert Profiler into InternalProfileShardResults, which
|
||||||
|
* can be serialized to other nodes, emitted as JSON, etc.
|
||||||
|
*
|
||||||
|
* @param profilers
|
||||||
|
* A list of Profilers to convert into
|
||||||
|
* InternalProfileShardResults
|
||||||
|
* @return A list of corresponding InternalProfileShardResults
|
||||||
|
*/
|
||||||
|
public static List<ProfileShardResult> buildShardResults(List<QueryProfiler> profilers) {
|
||||||
|
List<ProfileShardResult> results = new ArrayList<>(profilers.size());
|
||||||
|
for (QueryProfiler profiler : profilers) {
|
||||||
|
ProfileShardResult result = new ProfileShardResult(profiler.getQueryTree(), profiler.getRewriteTime(), profiler.getCollector());
|
||||||
|
results.add(result);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -55,7 +55,7 @@ import org.elasticsearch.search.internal.SearchContext;
|
||||||
import org.elasticsearch.search.profile.CollectorResult;
|
import org.elasticsearch.search.profile.CollectorResult;
|
||||||
import org.elasticsearch.search.profile.InternalProfileCollector;
|
import org.elasticsearch.search.profile.InternalProfileCollector;
|
||||||
import org.elasticsearch.search.profile.ProfileShardResult;
|
import org.elasticsearch.search.profile.ProfileShardResult;
|
||||||
import org.elasticsearch.search.profile.Profiler;
|
import org.elasticsearch.search.profile.SearchProfileShardResults;
|
||||||
import org.elasticsearch.search.rescore.RescorePhase;
|
import org.elasticsearch.search.rescore.RescorePhase;
|
||||||
import org.elasticsearch.search.rescore.RescoreSearchContext;
|
import org.elasticsearch.search.rescore.RescoreSearchContext;
|
||||||
import org.elasticsearch.search.sort.SortAndFormats;
|
import org.elasticsearch.search.sort.SortAndFormats;
|
||||||
|
@ -112,7 +112,8 @@ public class QueryPhase implements SearchPhase {
|
||||||
aggregationPhase.execute(searchContext);
|
aggregationPhase.execute(searchContext);
|
||||||
|
|
||||||
if (searchContext.getProfilers() != null) {
|
if (searchContext.getProfilers() != null) {
|
||||||
List<ProfileShardResult> shardResults = Profiler.buildShardResults(searchContext.getProfilers().getProfilers());
|
List<ProfileShardResult> shardResults = SearchProfileShardResults
|
||||||
|
.buildShardResults(searchContext.getProfilers().getProfilers());
|
||||||
searchContext.queryResult().profileResults(shardResults);
|
searchContext.queryResult().profileResults(shardResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,7 +385,8 @@ public class QueryPhase implements SearchPhase {
|
||||||
queryResult.topDocs(topDocsCallable.call(), sortValueFormats);
|
queryResult.topDocs(topDocsCallable.call(), sortValueFormats);
|
||||||
|
|
||||||
if (searchContext.getProfilers() != null) {
|
if (searchContext.getProfilers() != null) {
|
||||||
List<ProfileShardResult> shardResults = Profiler.buildShardResults(searchContext.getProfilers().getProfilers());
|
List<ProfileShardResult> shardResults = SearchProfileShardResults
|
||||||
|
.buildShardResults(searchContext.getProfilers().getProfilers());
|
||||||
searchContext.queryResult().profileResults(shardResults);
|
searchContext.queryResult().profileResults(shardResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.apache.lucene.search.TotalHitCountCollector;
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.util.IOUtils;
|
import org.apache.lucene.util.IOUtils;
|
||||||
import org.apache.lucene.util.TestUtil;
|
import org.apache.lucene.util.TestUtil;
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
|
||||||
import org.elasticsearch.index.engine.Engine;
|
import org.elasticsearch.index.engine.Engine;
|
||||||
import org.elasticsearch.search.internal.ContextIndexSearcher;
|
import org.elasticsearch.search.internal.ContextIndexSearcher;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
@ -84,45 +83,45 @@ public class ProfileTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBasic() throws IOException {
|
public void testBasic() throws IOException {
|
||||||
Profiler profiler = new Profiler();
|
QueryProfiler profiler = new QueryProfiler();
|
||||||
searcher.setProfiler(profiler);
|
searcher.setProfiler(profiler);
|
||||||
Query query = new TermQuery(new Term("foo", "bar"));
|
Query query = new TermQuery(new Term("foo", "bar"));
|
||||||
searcher.search(query, 1);
|
searcher.search(query, 1);
|
||||||
List<ProfileResult> results = profiler.getQueryTree();
|
List<ProfileResult> results = profiler.getQueryTree();
|
||||||
assertEquals(1, results.size());
|
assertEquals(1, results.size());
|
||||||
Map<String, Long> breakdown = results.get(0).getTimeBreakdown();
|
Map<String, Long> breakdown = results.get(0).getTimeBreakdown();
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.ADVANCE.toString()).longValue(), equalTo(0L));
|
assertThat(breakdown.get(QueryTimingType.ADVANCE.toString()).longValue(), equalTo(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.SCORE.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.SCORE.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.MATCH.toString()).longValue(), equalTo(0L));
|
assertThat(breakdown.get(QueryTimingType.MATCH.toString()).longValue(), equalTo(0L));
|
||||||
|
|
||||||
long rewriteTime = profiler.getRewriteTime();
|
long rewriteTime = profiler.getRewriteTime();
|
||||||
assertThat(rewriteTime, greaterThan(0L));
|
assertThat(rewriteTime, greaterThan(0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNoScoring() throws IOException {
|
public void testNoScoring() throws IOException {
|
||||||
Profiler profiler = new Profiler();
|
QueryProfiler profiler = new QueryProfiler();
|
||||||
searcher.setProfiler(profiler);
|
searcher.setProfiler(profiler);
|
||||||
Query query = new TermQuery(new Term("foo", "bar"));
|
Query query = new TermQuery(new Term("foo", "bar"));
|
||||||
searcher.search(query, 1, Sort.INDEXORDER); // scores are not needed
|
searcher.search(query, 1, Sort.INDEXORDER); // scores are not needed
|
||||||
List<ProfileResult> results = profiler.getQueryTree();
|
List<ProfileResult> results = profiler.getQueryTree();
|
||||||
assertEquals(1, results.size());
|
assertEquals(1, results.size());
|
||||||
Map<String, Long> breakdown = results.get(0).getTimeBreakdown();
|
Map<String, Long> breakdown = results.get(0).getTimeBreakdown();
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.ADVANCE.toString()).longValue(), equalTo(0L));
|
assertThat(breakdown.get(QueryTimingType.ADVANCE.toString()).longValue(), equalTo(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.SCORE.toString()).longValue(), equalTo(0L));
|
assertThat(breakdown.get(QueryTimingType.SCORE.toString()).longValue(), equalTo(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.MATCH.toString()).longValue(), equalTo(0L));
|
assertThat(breakdown.get(QueryTimingType.MATCH.toString()).longValue(), equalTo(0L));
|
||||||
|
|
||||||
long rewriteTime = profiler.getRewriteTime();
|
long rewriteTime = profiler.getRewriteTime();
|
||||||
assertThat(rewriteTime, greaterThan(0L));
|
assertThat(rewriteTime, greaterThan(0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUseIndexStats() throws IOException {
|
public void testUseIndexStats() throws IOException {
|
||||||
Profiler profiler = new Profiler();
|
QueryProfiler profiler = new QueryProfiler();
|
||||||
searcher.setProfiler(profiler);
|
searcher.setProfiler(profiler);
|
||||||
Query query = new TermQuery(new Term("foo", "bar"));
|
Query query = new TermQuery(new Term("foo", "bar"));
|
||||||
searcher.count(query); // will use index stats
|
searcher.count(query); // will use index stats
|
||||||
|
@ -134,7 +133,7 @@ public class ProfileTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testApproximations() throws IOException {
|
public void testApproximations() throws IOException {
|
||||||
Profiler profiler = new Profiler();
|
QueryProfiler profiler = new QueryProfiler();
|
||||||
Engine.Searcher engineSearcher = new Engine.Searcher("test", new IndexSearcher(reader));
|
Engine.Searcher engineSearcher = new Engine.Searcher("test", new IndexSearcher(reader));
|
||||||
// disable query caching since we want to test approximations, which won't
|
// disable query caching since we want to test approximations, which won't
|
||||||
// be exposed on a cached entry
|
// be exposed on a cached entry
|
||||||
|
@ -145,12 +144,12 @@ public class ProfileTests extends ESTestCase {
|
||||||
List<ProfileResult> results = profiler.getQueryTree();
|
List<ProfileResult> results = profiler.getQueryTree();
|
||||||
assertEquals(1, results.size());
|
assertEquals(1, results.size());
|
||||||
Map<String, Long> breakdown = results.get(0).getTimeBreakdown();
|
Map<String, Long> breakdown = results.get(0).getTimeBreakdown();
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.ADVANCE.toString()).longValue(), equalTo(0L));
|
assertThat(breakdown.get(QueryTimingType.ADVANCE.toString()).longValue(), equalTo(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.SCORE.toString()).longValue(), equalTo(0L));
|
assertThat(breakdown.get(QueryTimingType.SCORE.toString()).longValue(), equalTo(0L));
|
||||||
assertThat(breakdown.get(ProfileBreakdown.TimingType.MATCH.toString()).longValue(), greaterThan(0L));
|
assertThat(breakdown.get(QueryTimingType.MATCH.toString()).longValue(), greaterThan(0L));
|
||||||
|
|
||||||
long rewriteTime = profiler.getRewriteTime();
|
long rewriteTime = profiler.getRewriteTime();
|
||||||
assertThat(rewriteTime, greaterThan(0L));
|
assertThat(rewriteTime, greaterThan(0L));
|
||||||
|
|
Loading…
Reference in New Issue