7171import org .opensearch .search .lookup .SearchLookup ;
7272import org .opensearch .search .lookup .SourceLookup ;
7373import org .opensearch .search .profile .Timer ;
74+ import org .opensearch .search .profile .fetch .FetchProfileBreakdown ;
7475import org .opensearch .search .profile .fetch .FetchTimingType ;
7576
7677import java .io .IOException ;
@@ -105,10 +106,9 @@ public FetchPhase(List<FetchSubPhase> fetchSubPhases) {
105106 }
106107
107108 public void execute (SearchContext context ) {
108- Timer timer = null ;
109+ FetchProfileBreakdown profile = null ;
109110 if (context .getProfilers () != null ) {
110- timer = context .getProfilers ().getFetchProfiler ().getQueryBreakdown ("fetch" ).getTimer (FetchTimingType .EXECUTE_FETCH_PHASE );
111- timer .start ();
111+ profile = context .getProfilers ().getFetchProfiler ().getQueryBreakdown ("fetch" );
112112 }
113113 try {
114114 if (LOGGER .isTraceEnabled ()) {
@@ -131,16 +131,39 @@ public void execute(SearchContext context) {
131131 docs [index ] = new DocIdToIndex (context .docIdsToLoad ()[context .docIdsToLoadFrom () + index ], index );
132132 }
133133 // make sure that we iterate in doc id order
134- Arrays .sort (docs );
134+ if (profile != null ) {
135+ Timer t = profile .getTimer (FetchTimingType .SORT_DOC_IDS );
136+ t .start ();
137+ Arrays .sort (docs );
138+ t .stop ();
139+ } else {
140+ Arrays .sort (docs );
141+ }
135142
136143 Map <String , Set <String >> storedToRequestedFields = new HashMap <>();
137- FieldsVisitor fieldsVisitor = createStoredFieldsVisitor (context , storedToRequestedFields );
144+ FieldsVisitor fieldsVisitor ;
145+ if (profile != null ) {
146+ Timer t = profile .getTimer (FetchTimingType .CREATE_STORED_FIELDS_VISITOR );
147+ t .start ();
148+ fieldsVisitor = createStoredFieldsVisitor (context , storedToRequestedFields );
149+ t .stop ();
150+ } else {
151+ fieldsVisitor = createStoredFieldsVisitor (context , storedToRequestedFields );
152+ }
138153
139154 FetchContext fetchContext = new FetchContext (context );
140155
141156 SearchHit [] hits = new SearchHit [context .docIdsToLoadSize ()];
142157
143- List <FetchSubPhaseProcessor > processors = getProcessors (context .shardTarget (), fetchContext );
158+ List <Tuple <FetchSubPhaseProcessor , FetchSubPhase >> processors ;
159+ if (profile != null ) {
160+ Timer t = profile .getTimer (FetchTimingType .BUILD_SUB_PHASE_PROCESSORS );
161+ t .start ();
162+ processors = getProcessors (context .shardTarget (), fetchContext );
163+ t .stop ();
164+ } else {
165+ processors = getProcessors (context .shardTarget (), fetchContext );
166+ }
144167
145168 int currentReaderIndex = -1 ;
146169 LeafReaderContext currentReaderContext = null ;
@@ -154,7 +177,14 @@ public void execute(SearchContext context) {
154177 try {
155178 int readerIndex = ReaderUtil .subIndex (docId , context .searcher ().getIndexReader ().leaves ());
156179 if (currentReaderIndex != readerIndex ) {
157- currentReaderContext = context .searcher ().getIndexReader ().leaves ().get (readerIndex );
180+ if (profile != null ) {
181+ Timer t = profile .getTimer (FetchTimingType .GET_LEAF_READER );
182+ t .start ();
183+ currentReaderContext = context .searcher ().getIndexReader ().leaves ().get (readerIndex );
184+ t .stop ();
185+ } else {
186+ currentReaderContext = context .searcher ().getIndexReader ().leaves ().get (readerIndex );
187+ }
158188 currentReaderIndex = readerIndex ;
159189 if (currentReaderContext .reader () instanceof SequentialStoredFieldsLeafReader
160190 && hasSequentialDocs
@@ -168,22 +198,48 @@ public void execute(SearchContext context) {
168198 } else {
169199 fieldReader = currentReaderContext .reader ().storedFields ()::document ;
170200 }
171- for (FetchSubPhaseProcessor processor : processors ) {
172- processor .setNextReader (currentReaderContext );
201+ for (Tuple < FetchSubPhaseProcessor , FetchSubPhase > p : processors ) {
202+ p . v1 () .setNextReader (currentReaderContext );
173203 }
174204 }
175205 assert currentReaderContext != null ;
176- HitContext hit = prepareHitContext (
177- context ,
178- fetchContext .searchLookup (),
179- fieldsVisitor ,
180- docId ,
181- storedToRequestedFields ,
182- currentReaderContext ,
183- fieldReader
184- );
185- for (FetchSubPhaseProcessor processor : processors ) {
186- processor .process (hit );
206+ HitContext hit ;
207+ if (profile != null ) {
208+ Timer t = profile .getTimer (FetchTimingType .PREPARE_HIT_CONTEXT );
209+ t .start ();
210+ hit = prepareHitContext (
211+ context ,
212+ fetchContext .searchLookup (),
213+ fieldsVisitor ,
214+ docId ,
215+ storedToRequestedFields ,
216+ currentReaderContext ,
217+ fieldReader
218+ );
219+ t .stop ();
220+ } else {
221+ hit = prepareHitContext (
222+ context ,
223+ fetchContext .searchLookup (),
224+ fieldsVisitor ,
225+ docId ,
226+ storedToRequestedFields ,
227+ currentReaderContext ,
228+ fieldReader
229+ );
230+ }
231+ for (Tuple <FetchSubPhaseProcessor , FetchSubPhase > p : processors ) {
232+ if (profile != null ) {
233+ FetchTimingType tt = timingTypeFor (p .v2 ());
234+ if (tt != null ) {
235+ Timer st = profile .getTimer (tt );
236+ st .start ();
237+ p .v1 ().process (hit );
238+ st .stop ();
239+ continue ;
240+ }
241+ }
242+ p .v1 ().process (hit );
187243 }
188244 hits [docs [index ].index ] = hit .hit ();
189245 } catch (Exception e ) {
@@ -195,22 +251,28 @@ public void execute(SearchContext context) {
195251 }
196252
197253 TotalHits totalHits = context .queryResult ().getTotalHits ();
198- context .fetchResult ().hits (new SearchHits (hits , totalHits , context .queryResult ().getMaxScore ()));
254+ if (profile != null ) {
255+ Timer t = profile .getTimer (FetchTimingType .BUILD_SEARCH_HITS );
256+ t .start ();
257+ context .fetchResult ().hits (new SearchHits (hits , totalHits , context .queryResult ().getMaxScore ()));
258+ t .stop ();
259+ } else {
260+ context .fetchResult ().hits (new SearchHits (hits , totalHits , context .queryResult ().getMaxScore ()));
261+ }
199262 } finally {
200- if (timer != null ) {
201- timer .stop ();
263+ if (profile != null ) {
202264 context .getProfilers ().getFetchProfiler ().pollLastElement ();
203265 }
204266 }
205267 }
206268
207- List <FetchSubPhaseProcessor > getProcessors (SearchShardTarget target , FetchContext context ) {
269+ List <Tuple < FetchSubPhaseProcessor , FetchSubPhase > > getProcessors (SearchShardTarget target , FetchContext context ) {
208270 try {
209- List <FetchSubPhaseProcessor > processors = new ArrayList <>();
271+ List <Tuple < FetchSubPhaseProcessor , FetchSubPhase > > processors = new ArrayList <>();
210272 for (FetchSubPhase fsp : fetchSubPhases ) {
211273 FetchSubPhaseProcessor processor = fsp .getProcessor (context );
212274 if (processor != null ) {
213- processors .add (processor );
275+ processors .add (new Tuple <>( processor , fsp ) );
214276 }
215277 }
216278 return processors ;
@@ -219,6 +281,32 @@ List<FetchSubPhaseProcessor> getProcessors(SearchShardTarget target, FetchContex
219281 }
220282 }
221283
284+ private FetchTimingType timingTypeFor (FetchSubPhase phase ) {
285+ if (phase instanceof org .opensearch .search .fetch .subphase .ExplainPhase ) {
286+ return FetchTimingType .EXPLAIN ;
287+ } else if (phase instanceof org .opensearch .search .fetch .subphase .FetchDocValuesPhase ) {
288+ return FetchTimingType .FETCH_DOC_VALUES ;
289+ } else if (phase instanceof org .opensearch .search .fetch .subphase .ScriptFieldsPhase ) {
290+ return FetchTimingType .SCRIPT_FIELDS ;
291+ } else if (phase instanceof org .opensearch .search .fetch .subphase .FetchSourcePhase ) {
292+ return FetchTimingType .FETCH_SOURCE ;
293+ } else if (phase instanceof org .opensearch .search .fetch .subphase .FetchFieldsPhase ) {
294+ return FetchTimingType .FETCH_FIELDS ;
295+ } else if (phase instanceof org .opensearch .search .fetch .subphase .FetchVersionPhase ) {
296+ return FetchTimingType .FETCH_VERSION ;
297+ } else if (phase instanceof org .opensearch .search .fetch .subphase .SeqNoPrimaryTermPhase ) {
298+ return FetchTimingType .SEQ_NO_PRIMARY_TERM ;
299+ } else if (phase instanceof org .opensearch .search .fetch .subphase .MatchedQueriesPhase ) {
300+ return FetchTimingType .MATCHED_QUERIES ;
301+ } else if (phase instanceof org .opensearch .search .fetch .subphase .highlight .HighlightPhase ) {
302+ return FetchTimingType .HIGHLIGHT ;
303+ } else if (phase instanceof org .opensearch .search .fetch .subphase .FetchScorePhase ) {
304+ return FetchTimingType .FETCH_SCORE ;
305+ } else {
306+ return null ;
307+ }
308+ }
309+
222310 static class DocIdToIndex implements Comparable <DocIdToIndex > {
223311 final int docId ;
224312 final int index ;
0 commit comments