Hi, I wonder if anyone has any feedback on a performance change that I am working on making.
One benefit of reducing concurrency in a server application is that a small number of requests can complete more quickly than if they had to compete against a large number of running threads for object locks (Java or externally in a database). I would like have a Tomcat configuration option to set the max number of concurrent threads that can service user requests. You might configure Tomcat to handle 800 http client connections but set the max concurrent requests to 20 (perhaps higher if you have more CPUs). I like to refer to the max concurrent requests setting as the throttle size (if there is a better term, let me know). I modified the Tomcat Thread.run code to use Doug Lea's semaphore support but didn't expose a configuration option (haven't learned how to do that yet). My basic change is to allow users to specify the max number of concurrent servlet requests that can run. If an application has a high level of concurrency, end users may get more consistent response time with this change. If an application has a low level of concurrency, my change doesn't help as their application only has a few threads running concurrently anyway. This also reduces resource use on other tiers. For example, if you are supporting 500 users with a Tomcat instance, you don't need a database connection pool size of 500, instead set the throttle size to 20 and create a database connection pool size of 20. Current status of the change: 1. org.apache.tomcat.util.threads.ThreadPool.CONCURRENT_THREADS is hardcoded to a value of 18, should be a configurable option. 2. I hacked the build scripts to include Doug Lea's concurrent.jar but probably didn't make these changes correctly. I could switch to using the Java 1.5 implementation of the Concurrent package but we would still need to do something for Java 1.4 compatibility. Any suggestions on completing this enhancement are appreciated. Please include my [EMAIL PROTECTED] email address in your response. Thank you, Scott Marlow --- Tomcat newbie
Index: ./jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/threads/ThreadPool.java =================================================================== RCS file: /home/cvspublic/jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/threads/ThreadPool.java,v retrieving revision 1.30 diff -u -r1.30 ThreadPool.java --- ./jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/threads/ThreadPool.java 11 Dec 2004 03:52:56 -0000 1.30 +++ ./jakarta-tomcat-connectors/util/java/org/apache/tomcat/util/threads/ThreadPool.java 4 May 2005 13:32:57 -0000 @@ -20,6 +20,9 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tomcat.util.res.StringManager; +import EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore; +import EDU.oswego.cs.dl.util.concurrent.NullSync; +import EDU.oswego.cs.dl.util.concurrent.Sync; /** * A thread pool that is trying to copy the apache process management. @@ -46,7 +49,8 @@ public static final int MAX_SPARE_THREADS = 50; public static final int MIN_SPARE_THREADS = 4; public static final int WORK_WAIT_TIMEOUT = 60*1000; - + public static final int UNLIMITED_CONCURRENT_THREADS = -1; + public static final int CONCURRENT_THREADS = 18; /* * Where the threads are held. */ @@ -74,6 +78,17 @@ protected int maxSpareThreads; /* + * number of threads that can run concurrently. + */ + protected int concurrentThreads; + + /* + * Doug Lea's Semaphore implementation used to + * control number of concurrent requests running. + */ + protected Sync concurrencySemaphore; + + /* * Number of threads in the pool. */ protected int currentThreadCount; @@ -123,6 +138,7 @@ currentThreadCount = 0; currentThreadsBusy = 0; stopThePool = false; + concurrentThreads = CONCURRENT_THREADS; } @@ -143,6 +159,11 @@ adjustLimits(); + if(concurrentThreads < 1) + concurrencySemaphore = new NullSync(); + else + concurrencySemaphore = new FIFOSemaphore(concurrentThreads); + pool = new ControlRunnable[maxThreads]; openThreads(minSpareThreads); @@ -309,6 +330,10 @@ c.runIt(r); } + private Sync getConcurrencySemaphore() { + return concurrencySemaphore; + } + private ControlRunnable findControlRunnable() { ControlRunnable c=null; @@ -680,13 +705,24 @@ } if (_shouldRun) { - if (_toRun != null) { - _toRun.runIt(t.getThreadData(p)); - } else if (toRunRunnable != null) { - toRunRunnable.run(); - } else { - if (ThreadPool.log.isDebugEnabled()) - ThreadPool.log.debug("No toRun ???"); + Sync concurrencySemaphore = p.getConcurrencySemaphore(); + boolean _shouldReleaseSemaphore = false; + try { + concurrencySemaphore.acquire(); + _shouldReleaseSemaphore = true; + if (_toRun != null) { + _toRun.runIt(t.getThreadData(p)); + } else if (toRunRunnable != null) { + toRunRunnable.run(); + } else { + if (ThreadPool.log.isDebugEnabled()) + ThreadPool.log.debug("No toRun ???"); + } + } + finally { + if (_shouldReleaseSemaphore) { + concurrencySemaphore.release(); + } } } } catch (Throwable t) {
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]