Bläddra i källkod

Don't generate stacktrace in EarlyTerminationException and TimeExceededException (#95910)

Ignacio Vera 2 år sedan
förälder
incheckning
e208992b66

+ 5 - 0
docs/changelog/95910.yaml

@@ -0,0 +1,5 @@
+pr: 95910
+summary: Don't generate stacktrace in `EarlyTerminationException` and `TimeExceededException`
+area: Search
+type: enhancement
+issues: []

+ 4 - 15
server/src/main/java/org/elasticsearch/search/aggregations/AggregationPhase.java

@@ -9,7 +9,6 @@ package org.elasticsearch.search.aggregations;
 
 import org.apache.lucene.search.Collector;
 import org.elasticsearch.action.search.SearchShardTask;
-import org.elasticsearch.search.SearchService;
 import org.elasticsearch.search.aggregations.support.TimeSeriesIndexSearcher;
 import org.elasticsearch.search.internal.SearchContext;
 import org.elasticsearch.search.profile.query.CollectorResult;
@@ -75,21 +74,11 @@ public class AggregationPhase {
             });
         }
 
-        boolean timeoutSet = context.scrollContext() == null
-            && context.timeout() != null
-            && context.timeout().equals(SearchService.NO_TIMEOUT) == false;
-
-        if (timeoutSet) {
-            final long startTime = context.getRelativeTimeInMillis();
-            final long timeout = context.timeout().millis();
-            final long maxTime = startTime + timeout;
-            cancellationChecks.add(() -> {
-                final long time = context.getRelativeTimeInMillis();
-                if (time > maxTime) {
-                    throw new QueryPhase.TimeExceededException();
-                }
-            });
+        final Runnable timeoutRunnable = QueryPhase.getTimeoutCheck(context);
+        if (timeoutRunnable != null) {
+            cancellationChecks.add(timeoutRunnable);
         }
+
         return cancellationChecks;
     }
 

+ 8 - 2
server/src/main/java/org/elasticsearch/search/query/EarlyTerminatingCollector.java

@@ -21,11 +21,17 @@ import java.io.IOException;
 /**
  * A {@link Collector} that early terminates collection after <code>maxCountHits</code> docs have been collected.
  */
-public class EarlyTerminatingCollector extends FilterCollector {
+class EarlyTerminatingCollector extends FilterCollector {
     static final class EarlyTerminationException extends RuntimeException {
-        EarlyTerminationException(String msg) {
+        private EarlyTerminationException(String msg) {
             super(msg);
         }
+
+        @Override
+        public Throwable fillInStackTrace() {
+            // never re-thrown so we can save the expensive stacktrace
+            return this;
+        }
     }
 
     private final int maxCountHits;

+ 32 - 19
server/src/main/java/org/elasticsearch/search/query/QueryPhase.java

@@ -259,27 +259,13 @@ public class QueryPhase {
                 );
             }
 
-            boolean timeoutSet = scrollContext == null
-                && searchContext.timeout() != null
-                && searchContext.timeout().equals(SearchService.NO_TIMEOUT) == false;
-
-            final Runnable timeoutRunnable;
-            if (timeoutSet) {
-                final long startTime = searchContext.getRelativeTimeInMillis();
-                final long timeout = searchContext.timeout().millis();
-                final long maxTime = startTime + timeout;
-                timeoutRunnable = searcher.addQueryCancellation(() -> {
-                    final long time = searchContext.getRelativeTimeInMillis();
-                    if (time > maxTime) {
-                        throw new TimeExceededException();
-                    }
-                });
-            } else {
-                timeoutRunnable = null;
+            final Runnable timeoutRunnable = getTimeoutCheck(searchContext);
+            if (timeoutRunnable != null) {
+                searcher.addQueryCancellation(timeoutRunnable);
             }
 
             try {
-                searchWithCollectorManager(searchContext, searcher, query, collectorManager, timeoutSet);
+                searchWithCollectorManager(searchContext, searcher, query, collectorManager, timeoutRunnable != null);
                 queryResult.topDocs(topDocsFactory.topDocsAndMaxScore(), topDocsFactory.sortValueFormats);
                 ExecutorService executor = searchContext.indexShard().getThreadPool().executor(ThreadPool.Names.SEARCH);
                 assert executor instanceof EWMATrackingEsThreadPoolExecutor
@@ -364,7 +350,34 @@ public class QueryPhase {
         return true;
     }
 
-    public static class TimeExceededException extends RuntimeException {}
+    public static Runnable getTimeoutCheck(SearchContext searchContext) {
+        boolean timeoutSet = searchContext.scrollContext() == null
+            && searchContext.timeout() != null
+            && searchContext.timeout().equals(SearchService.NO_TIMEOUT) == false;
+
+        if (timeoutSet) {
+            final long startTime = searchContext.getRelativeTimeInMillis();
+            final long timeout = searchContext.timeout().millis();
+            final long maxTime = startTime + timeout;
+            return () -> {
+                final long time = searchContext.getRelativeTimeInMillis();
+                if (time > maxTime) {
+                    throw new TimeExceededException();
+                }
+            };
+        } else {
+            return null;
+        }
+    }
+
+    private static class TimeExceededException extends RuntimeException {
+
+        @Override
+        public Throwable fillInStackTrace() {
+            // never re-thrown so we can save the expensive stacktrace
+            return this;
+        }
+    }
 
     private static final Collector EMPTY_COLLECTOR = new SimpleCollector() {
         @Override