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]

Reply via email to