You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2021/10/11 14:04:18 UTC
[tomcat] 01/02: Improve Connector stop performance - primarily to
speed up tests
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 3d60c5edc601bbb7f671d48bb4b7e77057dcaf48
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 2938135..832119a 100644
--- a/java/org/apache/tomcat/util/net/AbstractEndpoint.java
+++ b/java/org/apache/tomcat/util/net/AbstractEndpoint.java
@@ -1032,12 +1032,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 c526145..b1083b2 100644
--- a/java/org/apache/tomcat/util/net/Acceptor.java
+++ b/java/org/apache/tomcat/util/net/Acceptor.java
@@ -68,18 +68,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 2c56ddd..5fb0477 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 94bbb54..01da994 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.1.0-M7 (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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org