This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.0.x by this push: new 21ec01f Improve Connector stop performance - primarily to speed up tests 21ec01f is described below commit 21ec01ff8f28c09bf821ec0d40c449a923803022 Author: Mark Thomas <ma...@apache.org> AuthorDate: Mon Oct 11 13:51:05 2021 +0100 Improve Connector stop performance - primarily to speed up tests --- .../apache/tomcat/util/net/AbstractEndpoint.java | 17 +++++++---- java/org/apache/tomcat/util/net/Acceptor.java | 35 ++++++++++++++++++---- java/org/apache/tomcat/util/net/Nio2Endpoint.java | 4 +-- webapps/docs/changelog.xml | 8 +++++ 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/java/org/apache/tomcat/util/net/AbstractEndpoint.java b/java/org/apache/tomcat/util/net/AbstractEndpoint.java index 437e1da..cde1dd6 100644 --- a/java/org/apache/tomcat/util/net/AbstractEndpoint.java +++ b/java/org/apache/tomcat/util/net/AbstractEndpoint.java @@ -1042,12 +1042,17 @@ public abstract class AbstractEndpoint<S,U> { getLog().debug("Socket unlock completed for:" + unlockAddress); } } - // Wait for upto 1000ms acceptor threads to unlock - long waitLeft = 1000; - while (waitLeft > 0 && - acceptor.getState() == AcceptorState.RUNNING) { - Thread.sleep(5); - waitLeft -= 5; + // Wait for up to 1000ms acceptor threads to unlock. Particularly + // for the unit tests, we want to exit this loop as quickly as + // possible. However, we also don't want to trigger excessive CPU + // usage if the unlock takes longer than expected. Therefore, we + // initially wait for the unlock in a tight loop but if that takes + // more than 1ms we start using short sleeps to reduce CPU usage. + long startTime = System.nanoTime(); + while (startTime + 1_000_000_000 > System.nanoTime() && acceptor.getState() == AcceptorState.RUNNING) { + if (startTime + 1_000_000 < System.nanoTime()) { + Thread.sleep(1); + } } } catch(Throwable t) { ExceptionUtils.handleThrowable(t); diff --git a/java/org/apache/tomcat/util/net/Acceptor.java b/java/org/apache/tomcat/util/net/Acceptor.java index ff810e9..3fa4f96 100644 --- a/java/org/apache/tomcat/util/net/Acceptor.java +++ b/java/org/apache/tomcat/util/net/Acceptor.java @@ -69,18 +69,41 @@ public class Acceptor<U> implements Runnable { public void run() { int errorDelay = 0; + long pauseStart = 0; try { // Loop until we receive a shutdown command while (!stopCalled) { - // Loop if endpoint is paused + // Loop if endpoint is paused. + // There are two likely scenarios here. + // The first scenario is that Tomcat is shutting down. In this + // case - and particularly for the unit tests - we want to exit + // this loop as quickly as possible. The second scenario is a + // genuine pause of the connector. In this case we want to avoid + // excessive CPU usage. + // Therefore, we start with a tight loop but if there isn't a + // rapid transition to stop then sleeps are introduced. + // < 1ms - tight loop + // 1ms to 10ms - 1ms sleep + // > 10ms - 10ms sleep while (endpoint.isPaused() && !stopCalled) { - state = AcceptorState.PAUSED; - try { - Thread.sleep(50); - } catch (InterruptedException e) { - // Ignore + if (state != AcceptorState.PAUSED) { + pauseStart = System.nanoTime(); + // Entered pause state + state = AcceptorState.PAUSED; + } + if ((System.nanoTime() - pauseStart) > 1_000_000) { + // Paused for more than 1ms + try { + if ((System.nanoTime() - pauseStart) > 10_000_000) { + Thread.sleep(10); + } else { + Thread.sleep(1); + } + } catch (InterruptedException e) { + // Ignore + } } } diff --git a/java/org/apache/tomcat/util/net/Nio2Endpoint.java b/java/org/apache/tomcat/util/net/Nio2Endpoint.java index 3ac5324..be724c4 100644 --- a/java/org/apache/tomcat/util/net/Nio2Endpoint.java +++ b/java/org/apache/tomcat/util/net/Nio2Endpoint.java @@ -253,8 +253,8 @@ public class Nio2Endpoint extends AbstractJsseEndpoint<Nio2Channel,AsynchronousS try { long timeout = getExecutorTerminationTimeoutMillis(); while (timeout > 0 && !allClosed) { - timeout -= 100; - Thread.sleep(100); + timeout -= 1; + Thread.sleep(1); } threadGroup.shutdownNow(); if (timeout > 0) { diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index bf789bb..4fadb0b 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -105,6 +105,14 @@ issues do not "pop up" wrt. others). --> <section name="Tomcat 10.0.13 (markt)" rtext="in development"> + <subsection name="Coyote"> + <changelog> + <scode> + Improve performance of Connector shutdown - primarily to reduce the time + it takes to run the test suite. (markt) + </scode> + </changelog> + </subsection> <subsection name="Jasper"> <changelog> <update> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org