diff --git a/core/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java b/core/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java index a8ecc7a508c..36fe562a568 100644 --- a/core/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java +++ b/core/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java @@ -51,7 +51,7 @@ import org.elasticsearch.search.fetch.FetchSearchResultProvider; import org.elasticsearch.search.internal.InternalSearchHit; import org.elasticsearch.search.internal.InternalSearchHits; 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.query.QuerySearchResult; import org.elasticsearch.search.query.QuerySearchResultProvider; @@ -405,14 +405,14 @@ public class SearchPhaseController extends AbstractComponent { } //Collect profile results - InternalProfileShardResults shardResults = null; + SearchProfileShardResults shardResults = null; if (!queryResults.isEmpty() && firstResult.profileResults() != null) { Map> profileResults = new HashMap<>(queryResults.size()); for (AtomicArray.Entry entry : queryResults) { String key = entry.value.queryResult().shardTarget().toString(); profileResults.put(key, entry.value.queryResult().profileResults()); } - shardResults = new InternalProfileShardResults(profileResults); + shardResults = new SearchProfileShardResults(profileResults); } if (aggregations != null) { diff --git a/core/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java b/core/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java index c4df30716c7..471ce26d297 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java +++ b/core/src/main/java/org/elasticsearch/search/internal/ContextIndexSearcher.java @@ -33,9 +33,10 @@ import org.apache.lucene.search.Weight; import org.elasticsearch.common.lease.Releasable; import org.elasticsearch.index.engine.Engine; 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.Profiler; +import org.elasticsearch.search.profile.QueryProfiler; +import org.elasticsearch.search.profile.QueryTimingType; import java.io.IOException; @@ -54,7 +55,7 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable { private final Engine.Searcher engineSearcher; // TODO revisit moving the profiler to inheritance or wrapping model in the future - private Profiler profiler; + private QueryProfiler profiler; public ContextIndexSearcher(Engine.Searcher searcher, QueryCache queryCache, QueryCachingPolicy queryCachingPolicy) { @@ -70,7 +71,7 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable { public void close() { } - public void setProfiler(Profiler profiler) { + public void setProfiler(QueryProfiler 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 // each invocation so that it can build an internal representation of the query // tree - ProfileBreakdown profile = profiler.getQueryBreakdown(query); - profile.startTime(ProfileBreakdown.TimingType.CREATE_WEIGHT); + QueryProfileBreakdown profile = profiler.getQueryBreakdown(query); + profile.startTime(QueryTimingType.CREATE_WEIGHT); final Weight weight; try { weight = super.createWeight(query, needsScores); diff --git a/core/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java b/core/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java index 1a2e1f70191..9c33889dc9c 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java +++ b/core/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java @@ -28,7 +28,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.aggregations.Aggregations; 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.suggest.Suggest; @@ -54,7 +54,7 @@ public class InternalSearchResponse implements Streamable, ToXContent { private Suggest suggest; - private InternalProfileShardResults profileResults; + private SearchProfileShardResults profileResults; private boolean timedOut; @@ -64,7 +64,7 @@ public class InternalSearchResponse implements Streamable, ToXContent { } public InternalSearchResponse(InternalSearchHits hits, InternalAggregations aggregations, Suggest suggest, - InternalProfileShardResults profileResults, boolean timedOut, Boolean terminatedEarly) { + SearchProfileShardResults profileResults, boolean timedOut, Boolean terminatedEarly) { this.hits = hits; this.aggregations = aggregations; this.suggest = suggest; @@ -141,7 +141,7 @@ public class InternalSearchResponse implements Streamable, ToXContent { terminatedEarly = in.readOptionalBoolean(); if (in.getVersion().onOrAfter(Version.V_2_2_0) && in.readBoolean()) { - profileResults = new InternalProfileShardResults(in); + profileResults = new SearchProfileShardResults(in); } else { profileResults = null; } diff --git a/core/src/main/java/org/elasticsearch/search/profile/ProfileBreakdown.java b/core/src/main/java/org/elasticsearch/search/profile/AbstractProfileBreakdown.java similarity index 78% rename from core/src/main/java/org/elasticsearch/search/profile/ProfileBreakdown.java rename to core/src/main/java/org/elasticsearch/search/profile/AbstractProfileBreakdown.java index a992f819874..f5cfc78d79e 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/ProfileBreakdown.java +++ b/core/src/main/java/org/elasticsearch/search/profile/AbstractProfileBreakdown.java @@ -21,7 +21,6 @@ package org.elasticsearch.search.profile; import java.util.Collections; import java.util.HashMap; -import java.util.Locale; 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, * scoring, etc). */ -public final class ProfileBreakdown { - - /** 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); - } - } +public abstract class AbstractProfileBreakdown> { /** * The accumulated timings for this query node @@ -52,23 +36,26 @@ public final class ProfileBreakdown { private final long[] timings; /** Scratch to store the current timing type. */ - private TimingType currentTimingType; + private T currentTimingType; /** * The temporary scratch space for holding start-times */ private long scratch; + private T[] timingTypes; + /** Sole constructor. */ - public ProfileBreakdown() { - timings = new long[TimingType.values().length]; + public AbstractProfileBreakdown(T[] timingTypes) { + this.timingTypes = timingTypes; + timings = new long[timingTypes.length]; } /** * Begin timing a query for a specific Timing context * @param timing The timing context being profiled */ - public void startTime(TimingType timing) { + public void startTime(T timing) { assert currentTimingType == null; assert scratch == 0; currentTimingType = timing; @@ -91,10 +78,10 @@ public final class ProfileBreakdown { 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 toTimingMap() { Map map = new HashMap<>(); - for (TimingType timingType : TimingType.values()) { + for (T timingType : timingTypes) { map.put(timingType.toString(), timings[timingType.ordinal()]); } return Collections.unmodifiableMap(map); @@ -104,7 +91,7 @@ public final class ProfileBreakdown { * Add other's timings into this breakdown * @param other Another Breakdown to merge with this one */ - public void merge(ProfileBreakdown other) { + public void merge(AbstractProfileBreakdown other) { assert(timings.length == other.timings.length); for (int i = 0; i < timings.length; ++i) { timings[i] += other.timings[i]; diff --git a/core/src/main/java/org/elasticsearch/search/profile/InternalProfileTree.java b/core/src/main/java/org/elasticsearch/search/profile/InternalQueryProfileTree.java similarity index 92% rename from core/src/main/java/org/elasticsearch/search/profile/InternalProfileTree.java rename to core/src/main/java/org/elasticsearch/search/profile/InternalQueryProfileTree.java index d7afd9c2fa0..9ebee2f1635 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/InternalProfileTree.java +++ b/core/src/main/java/org/elasticsearch/search/profile/InternalQueryProfileTree.java @@ -30,12 +30,12 @@ import java.util.concurrent.LinkedBlockingDeque; /** * 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 */ -final class InternalProfileTree { +final class InternalQueryProfileTree { - private ArrayList timings; + private ArrayList timings; /** Maps the Query to it's list of children. This is basically the dependency tree */ private ArrayList> tree; @@ -55,7 +55,7 @@ final class InternalProfileTree { private int currentToken = 0; - public InternalProfileTree() { + public InternalQueryProfileTree() { timings = new ArrayList<>(10); stack = new LinkedBlockingDeque<>(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 * 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 * @return A ProfileBreakdown for this query */ - public ProfileBreakdown getQueryBreakdown(Query query) { + public QueryProfileBreakdown getQueryBreakdown(Query query) { int token = currentToken; boolean stackEmpty = stack.isEmpty(); @@ -131,14 +131,14 @@ final class InternalProfileTree { * Helper method to add a new node to the dependency tree. * * 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 * * @param query The query to profile * @param token The assigned token for 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 tree.add(new ArrayList<>(5)); @@ -146,7 +146,7 @@ final class InternalProfileTree { // Save our query for lookup later queries.add(query); - ProfileBreakdown queryTimings = new ProfileBreakdown(); + QueryProfileBreakdown queryTimings = new QueryProfileBreakdown(); timings.add(token, queryTimings); return queryTimings; } @@ -180,7 +180,7 @@ final class InternalProfileTree { */ private ProfileResult doGetQueryTree(int token) { Query query = queries.get(token); - ProfileBreakdown breakdown = timings.get(token); + QueryProfileBreakdown breakdown = timings.get(token); Map timings = breakdown.toTimingMap(); List children = tree.get(token); List childrenProfileResults = Collections.emptyList(); diff --git a/core/src/main/java/org/elasticsearch/search/profile/ProfileResult.java b/core/src/main/java/org/elasticsearch/search/profile/ProfileResult.java index dc47f982a3c..165244e8d69 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/ProfileResult.java +++ b/core/src/main/java/org/elasticsearch/search/profile/ProfileResult.java @@ -45,22 +45,22 @@ import java.util.Map; */ final class ProfileResult implements Writeable, ToXContent { - private static final ParseField QUERY_TYPE = new ParseField("query_type"); - private static final ParseField LUCENE_DESCRIPTION = new ParseField("lucene"); + private static final ParseField TYPE = new ParseField("type"); + private static final ParseField DESCRIPTION = new ParseField("description"); private static final ParseField NODE_TIME = new ParseField("time"); private static final ParseField CHILDREN = new ParseField("children"); private static final ParseField BREAKDOWN = new ParseField("breakdown"); - private final String queryType; - private final String luceneDescription; + private final String type; + private final String description; private final Map timings; private final long nodeTime; private final List children; - public ProfileResult(String queryType, String luceneDescription, Map timings, List children, + public ProfileResult(String type, String description, Map timings, List children, long nodeTime) { - this.queryType = queryType; - this.luceneDescription = luceneDescription; + this.type = type; + this.description = description; this.timings = timings; this.children = children; this.nodeTime = nodeTime; @@ -70,8 +70,8 @@ final class ProfileResult implements Writeable, ToXContent { * Read from a stream. */ public ProfileResult(StreamInput in) throws IOException{ - this.queryType = in.readString(); - this.luceneDescription = in.readString(); + this.type = in.readString(); + this.description = in.readString(); this.nodeTime = in.readLong(); int timingsSize = in.readVInt(); @@ -90,8 +90,8 @@ final class ProfileResult implements Writeable, ToXContent { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeString(queryType); - out.writeString(luceneDescription); + out.writeString(type); + out.writeString(description); out.writeLong(nodeTime); // not Vlong because can be negative out.writeVInt(timings.size()); for (Map.Entry 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) */ public String getLuceneDescription() { - return luceneDescription; + return description; } /** * Retrieve the name of the query (e.g. "TermQuery") */ public String getQueryName() { - return queryType; + return type; } /** @@ -144,9 +144,9 @@ final class ProfileResult implements Writeable, ToXContent { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder = builder.startObject() - .field(QUERY_TYPE.getPreferredName(), queryType) - .field(LUCENE_DESCRIPTION.getPreferredName(), luceneDescription) - .field(NODE_TIME.getPreferredName(), String.format(Locale.US, "%.10gms", (double)(getTime() / 1000000.0))) + .field(TYPE.getPreferredName(), type) + .field(DESCRIPTION.getPreferredName(), description) + .field(NODE_TIME.getPreferredName(), String.format(Locale.US, "%.10gms", getTime() / 1000000.0)) .field(BREAKDOWN.getPreferredName(), timings); if (!children.isEmpty()) { diff --git a/core/src/main/java/org/elasticsearch/search/profile/ProfileScorer.java b/core/src/main/java/org/elasticsearch/search/profile/ProfileScorer.java index 972d176ca10..939ac85c871 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/ProfileScorer.java +++ b/core/src/main/java/org/elasticsearch/search/profile/ProfileScorer.java @@ -35,9 +35,9 @@ final class ProfileScorer extends Scorer { private final Scorer scorer; 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); this.scorer = scorer; this.profileWeight = w; @@ -51,7 +51,7 @@ final class ProfileScorer extends Scorer { @Override public float score() throws IOException { - profile.startTime(ProfileBreakdown.TimingType.SCORE); + profile.startTime(QueryTimingType.SCORE); try { return scorer.score(); } finally { @@ -78,10 +78,10 @@ final class ProfileScorer extends Scorer { public DocIdSetIterator iterator() { final DocIdSetIterator in = scorer.iterator(); return new DocIdSetIterator() { - + @Override public int advance(int target) throws IOException { - profile.startTime(ProfileBreakdown.TimingType.ADVANCE); + profile.startTime(QueryTimingType.ADVANCE); try { return in.advance(target); } finally { @@ -91,7 +91,7 @@ final class ProfileScorer extends Scorer { @Override public int nextDoc() throws IOException { - profile.startTime(ProfileBreakdown.TimingType.NEXT_DOC); + profile.startTime(QueryTimingType.NEXT_DOC); try { return in.nextDoc(); } finally { @@ -122,7 +122,7 @@ final class ProfileScorer extends Scorer { @Override public int advance(int target) throws IOException { - profile.startTime(ProfileBreakdown.TimingType.ADVANCE); + profile.startTime(QueryTimingType.ADVANCE); try { return inApproximation.advance(target); } finally { @@ -132,7 +132,7 @@ final class ProfileScorer extends Scorer { @Override public int nextDoc() throws IOException { - profile.startTime(ProfileBreakdown.TimingType.NEXT_DOC); + profile.startTime(QueryTimingType.NEXT_DOC); try { return inApproximation.nextDoc(); } finally { @@ -153,7 +153,7 @@ final class ProfileScorer extends Scorer { return new TwoPhaseIterator(approximation) { @Override public boolean matches() throws IOException { - profile.startTime(ProfileBreakdown.TimingType.MATCH); + profile.startTime(QueryTimingType.MATCH); try { return in.matches(); } finally { diff --git a/core/src/main/java/org/elasticsearch/search/profile/ProfileShardResult.java b/core/src/main/java/org/elasticsearch/search/profile/ProfileShardResult.java index 1353bb505ee..e35a3c2e2aa 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/ProfileShardResult.java +++ b/core/src/main/java/org/elasticsearch/search/profile/ProfileShardResult.java @@ -36,16 +36,16 @@ import java.util.List; */ public final class ProfileShardResult implements Writeable, ToXContent { - private final List profileResults; + private final List queryProfileResults; private final CollectorResult profileCollector; private final long rewriteTime; - public ProfileShardResult(List profileResults, long rewriteTime, + public ProfileShardResult(List queryProfileResults, long rewriteTime, CollectorResult profileCollector) { assert(profileCollector != null); - this.profileResults = profileResults; + this.queryProfileResults = queryProfileResults; this.profileCollector = profileCollector; this.rewriteTime = rewriteTime; } @@ -55,9 +55,9 @@ public final class ProfileShardResult implements Writeable, ToXContent { */ public ProfileShardResult(StreamInput in) throws IOException { int profileSize = in.readVInt(); - profileResults = new ArrayList<>(profileSize); + queryProfileResults = new ArrayList<>(profileSize); for (int j = 0; j < profileSize; j++) { - profileResults.add(new ProfileResult(in)); + queryProfileResults.add(new ProfileResult(in)); } profileCollector = new CollectorResult(in); @@ -66,8 +66,8 @@ public final class ProfileShardResult implements Writeable, ToXContent { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(profileResults.size()); - for (ProfileResult p : profileResults) { + out.writeVInt(queryProfileResults.size()); + for (ProfileResult p : queryProfileResults) { p.writeTo(out); } profileCollector.writeTo(out); @@ -76,7 +76,7 @@ public final class ProfileShardResult implements Writeable, ToXContent { public List getQueryResults() { - return Collections.unmodifiableList(profileResults); + return Collections.unmodifiableList(queryProfileResults); } public long getRewriteTime() { @@ -90,7 +90,7 @@ public final class ProfileShardResult implements Writeable, ToXContent { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startArray("query"); - for (ProfileResult p : profileResults) { + for (ProfileResult p : queryProfileResults) { p.toXContent(builder, params); } builder.endArray(); diff --git a/core/src/main/java/org/elasticsearch/search/profile/ProfileWeight.java b/core/src/main/java/org/elasticsearch/search/profile/ProfileWeight.java index 1ce5cd721fe..9546f691616 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/ProfileWeight.java +++ b/core/src/main/java/org/elasticsearch/search/profile/ProfileWeight.java @@ -38,9 +38,9 @@ import java.util.Set; public final class ProfileWeight extends Weight { 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); this.subQueryWeight = subQueryWeight; this.profile = profile; @@ -48,7 +48,7 @@ public final class ProfileWeight extends Weight { @Override public Scorer scorer(LeafReaderContext context) throws IOException { - profile.startTime(ProfileBreakdown.TimingType.BUILD_SCORER); + profile.startTime(QueryTimingType.BUILD_SCORER); final Scorer subQueryScorer; try { subQueryScorer = subQueryWeight.scorer(context); diff --git a/core/src/main/java/org/elasticsearch/search/profile/Profilers.java b/core/src/main/java/org/elasticsearch/search/profile/Profilers.java index 69a4544ccd7..38b69d38b15 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/Profilers.java +++ b/core/src/main/java/org/elasticsearch/search/profile/Profilers.java @@ -25,13 +25,13 @@ import java.util.ArrayList; import java.util.Collections; 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 { private final ContextIndexSearcher searcher; - private final List profilers; + private final List 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) { this.searcher = searcher; this.profilers = new ArrayList<>(); @@ -39,20 +39,20 @@ public final class Profilers { } /** Switch to a new profile. */ - public Profiler addProfiler() { - Profiler profiler = new Profiler(); + public QueryProfiler addProfiler() { + QueryProfiler profiler = new QueryProfiler(); searcher.setProfiler(profiler); profilers.add(profiler); return profiler; } /** Get the current profiler. */ - public Profiler getCurrent() { + public QueryProfiler getCurrent() { return profilers.get(profilers.size() - 1); } - /** Return the list of all created {@link Profiler}s so far. */ - public List getProfilers() { + /** Return the list of all created {@link QueryProfiler}s so far. */ + public List getProfilers() { return Collections.unmodifiableList(profilers); } diff --git a/core/src/main/java/org/elasticsearch/search/profile/QueryProfileBreakdown.java b/core/src/main/java/org/elasticsearch/search/profile/QueryProfileBreakdown.java new file mode 100644 index 00000000000..fdb13a49977 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/search/profile/QueryProfileBreakdown.java @@ -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 { + + /** Sole constructor. */ + public QueryProfileBreakdown() { + super(QueryTimingType.values()); + } +} diff --git a/core/src/main/java/org/elasticsearch/search/profile/Profiler.java b/core/src/main/java/org/elasticsearch/search/profile/QueryProfiler.java similarity index 75% rename from core/src/main/java/org/elasticsearch/search/profile/Profiler.java rename to core/src/main/java/org/elasticsearch/search/profile/QueryProfiler.java index 011b1593d35..f8fcf5fbf13 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/Profiler.java +++ b/core/src/main/java/org/elasticsearch/search/profile/QueryProfiler.java @@ -21,7 +21,6 @@ package org.elasticsearch.search.profile; import org.apache.lucene.search.Query; -import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -36,16 +35,16 @@ import java.util.Objects; * request may execute two searches (query + global agg). A Profiler just * 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 */ private InternalProfileCollector collector; - public Profiler() {} + public QueryProfiler() {} /** Set the collector that is associated with this profiler. */ 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 * rewriting phase */ - public ProfileBreakdown getQueryBreakdown(Query query) { + public QueryProfileBreakdown getQueryBreakdown(Query query) { return queryTree.getQueryBreakdown(query); } @@ -111,22 +110,5 @@ public final class Profiler { 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 buildShardResults(List profilers) { - List results = new ArrayList<>(profilers.size()); - for (Profiler profiler : profilers) { - ProfileShardResult result = new ProfileShardResult( - profiler.getQueryTree(), profiler.getRewriteTime(), profiler.getCollector()); - results.add(result); - } - return results; - } - } diff --git a/core/src/main/java/org/elasticsearch/search/profile/QueryTimingType.java b/core/src/main/java/org/elasticsearch/search/profile/QueryTimingType.java new file mode 100644 index 00000000000..5fb3b29dee3 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/search/profile/QueryTimingType.java @@ -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); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/elasticsearch/search/profile/InternalProfileShardResults.java b/core/src/main/java/org/elasticsearch/search/profile/SearchProfileShardResults.java similarity index 78% rename from core/src/main/java/org/elasticsearch/search/profile/InternalProfileShardResults.java rename to core/src/main/java/org/elasticsearch/search/profile/SearchProfileShardResults.java index 5aa42c45da3..a38c0813dc5 100644 --- a/core/src/main/java/org/elasticsearch/search/profile/InternalProfileShardResults.java +++ b/core/src/main/java/org/elasticsearch/search/profile/SearchProfileShardResults.java @@ -37,11 +37,11 @@ import java.util.stream.Collectors; * A container class to hold all the profile results across all shards. Internally * holds a map of shard ID -> Profiled results */ -public final class InternalProfileShardResults implements Writeable, ToXContent{ +public final class SearchProfileShardResults implements Writeable, ToXContent{ private Map> shardResults; - public InternalProfileShardResults(Map> shardResults) { + public SearchProfileShardResults(Map> shardResults) { Map> transformed = shardResults.entrySet() .stream() @@ -52,7 +52,7 @@ public final class InternalProfileShardResults implements Writeable, ToXContent{ this.shardResults = Collections.unmodifiableMap(transformed); } - public InternalProfileShardResults(StreamInput in) throws IOException { + public SearchProfileShardResults(StreamInput in) throws IOException { int size = in.readInt(); shardResults = new HashMap<>(size); @@ -105,4 +105,22 @@ public final class InternalProfileShardResults implements Writeable, ToXContent{ builder.endArray().endObject(); 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 buildShardResults(List profilers) { + List results = new ArrayList<>(profilers.size()); + for (QueryProfiler profiler : profilers) { + ProfileShardResult result = new ProfileShardResult(profiler.getQueryTree(), profiler.getRewriteTime(), profiler.getCollector()); + results.add(result); + } + return results; + } } diff --git a/core/src/main/java/org/elasticsearch/search/query/QueryPhase.java b/core/src/main/java/org/elasticsearch/search/query/QueryPhase.java index 1ae80337d76..da849828e7a 100644 --- a/core/src/main/java/org/elasticsearch/search/query/QueryPhase.java +++ b/core/src/main/java/org/elasticsearch/search/query/QueryPhase.java @@ -55,7 +55,7 @@ import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.profile.CollectorResult; import org.elasticsearch.search.profile.InternalProfileCollector; 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.RescoreSearchContext; import org.elasticsearch.search.sort.SortAndFormats; @@ -112,7 +112,8 @@ public class QueryPhase implements SearchPhase { aggregationPhase.execute(searchContext); if (searchContext.getProfilers() != null) { - List shardResults = Profiler.buildShardResults(searchContext.getProfilers().getProfilers()); + List shardResults = SearchProfileShardResults + .buildShardResults(searchContext.getProfilers().getProfilers()); searchContext.queryResult().profileResults(shardResults); } } @@ -384,7 +385,8 @@ public class QueryPhase implements SearchPhase { queryResult.topDocs(topDocsCallable.call(), sortValueFormats); if (searchContext.getProfilers() != null) { - List shardResults = Profiler.buildShardResults(searchContext.getProfilers().getProfilers()); + List shardResults = SearchProfileShardResults + .buildShardResults(searchContext.getProfilers().getProfilers()); searchContext.queryResult().profileResults(shardResults); } diff --git a/core/src/test/java/org/elasticsearch/search/profile/ProfileTests.java b/core/src/test/java/org/elasticsearch/search/profile/ProfileTests.java index afc1c7b3cbb..ebae8e64f32 100644 --- a/core/src/test/java/org/elasticsearch/search/profile/ProfileTests.java +++ b/core/src/test/java/org/elasticsearch/search/profile/ProfileTests.java @@ -35,7 +35,6 @@ import org.apache.lucene.search.TotalHitCountCollector; import org.apache.lucene.store.Directory; import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.TestUtil; -import org.elasticsearch.common.lucene.Lucene; import org.elasticsearch.index.engine.Engine; import org.elasticsearch.search.internal.ContextIndexSearcher; import org.elasticsearch.test.ESTestCase; @@ -84,45 +83,45 @@ public class ProfileTests extends ESTestCase { } public void testBasic() throws IOException { - Profiler profiler = new Profiler(); + QueryProfiler profiler = new QueryProfiler(); searcher.setProfiler(profiler); Query query = new TermQuery(new Term("foo", "bar")); searcher.search(query, 1); List results = profiler.getQueryTree(); assertEquals(1, results.size()); Map breakdown = results.get(0).getTimeBreakdown(); - assertThat(breakdown.get(ProfileBreakdown.TimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.ADVANCE.toString()).longValue(), equalTo(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.SCORE.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.MATCH.toString()).longValue(), equalTo(0L)); + assertThat(breakdown.get(QueryTimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.ADVANCE.toString()).longValue(), equalTo(0L)); + assertThat(breakdown.get(QueryTimingType.SCORE.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.MATCH.toString()).longValue(), equalTo(0L)); long rewriteTime = profiler.getRewriteTime(); assertThat(rewriteTime, greaterThan(0L)); } public void testNoScoring() throws IOException { - Profiler profiler = new Profiler(); + QueryProfiler profiler = new QueryProfiler(); searcher.setProfiler(profiler); Query query = new TermQuery(new Term("foo", "bar")); searcher.search(query, 1, Sort.INDEXORDER); // scores are not needed List results = profiler.getQueryTree(); assertEquals(1, results.size()); Map breakdown = results.get(0).getTimeBreakdown(); - assertThat(breakdown.get(ProfileBreakdown.TimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.ADVANCE.toString()).longValue(), equalTo(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.SCORE.toString()).longValue(), equalTo(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.MATCH.toString()).longValue(), equalTo(0L)); + assertThat(breakdown.get(QueryTimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.ADVANCE.toString()).longValue(), equalTo(0L)); + assertThat(breakdown.get(QueryTimingType.SCORE.toString()).longValue(), equalTo(0L)); + assertThat(breakdown.get(QueryTimingType.MATCH.toString()).longValue(), equalTo(0L)); long rewriteTime = profiler.getRewriteTime(); assertThat(rewriteTime, greaterThan(0L)); } public void testUseIndexStats() throws IOException { - Profiler profiler = new Profiler(); + QueryProfiler profiler = new QueryProfiler(); searcher.setProfiler(profiler); Query query = new TermQuery(new Term("foo", "bar")); searcher.count(query); // will use index stats @@ -134,7 +133,7 @@ public class ProfileTests extends ESTestCase { } public void testApproximations() throws IOException { - Profiler profiler = new Profiler(); + QueryProfiler profiler = new QueryProfiler(); Engine.Searcher engineSearcher = new Engine.Searcher("test", new IndexSearcher(reader)); // disable query caching since we want to test approximations, which won't // be exposed on a cached entry @@ -145,12 +144,12 @@ public class ProfileTests extends ESTestCase { List results = profiler.getQueryTree(); assertEquals(1, results.size()); Map breakdown = results.get(0).getTimeBreakdown(); - assertThat(breakdown.get(ProfileBreakdown.TimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.ADVANCE.toString()).longValue(), equalTo(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.SCORE.toString()).longValue(), equalTo(0L)); - assertThat(breakdown.get(ProfileBreakdown.TimingType.MATCH.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.CREATE_WEIGHT.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.BUILD_SCORER.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.NEXT_DOC.toString()).longValue(), greaterThan(0L)); + assertThat(breakdown.get(QueryTimingType.ADVANCE.toString()).longValue(), equalTo(0L)); + assertThat(breakdown.get(QueryTimingType.SCORE.toString()).longValue(), equalTo(0L)); + assertThat(breakdown.get(QueryTimingType.MATCH.toString()).longValue(), greaterThan(0L)); long rewriteTime = profiler.getRewriteTime(); assertThat(rewriteTime, greaterThan(0L));