Implemented the cache properly with its own attribute, removed one processor that...
authorfhanik <fhanik@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 14 Mar 2007 02:48:39 +0000 (02:48 +0000)
committerfhanik <fhanik@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 14 Mar 2007 02:48:39 +0000 (02:48 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@517977 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/tomcat/util/net/NioEndpoint.java
java/org/apache/tomcat/util/net/SocketProperties.java
webapps/docs/config/http.xml

index 990057c..0a32a03 100644 (file)
@@ -155,6 +155,40 @@ public class NioEndpoint {
     protected ServerSocketChannel serverSock = null;
 
     /**
+     * Cache for SocketProcessor objects
+     */
+    protected ConcurrentLinkedQueue<SocketProcessor> processorCache = new ConcurrentLinkedQueue<SocketProcessor>() {
+        protected AtomicInteger size = new AtomicInteger(0);
+        public boolean offer(SocketProcessor sc) {
+            sc.reset(null,null);
+            boolean offer = socketProperties.getProcessorCache()==-1?true:size.get()<socketProperties.getProcessorCache();
+            //avoid over growing our cache or add after we have stopped
+            if ( running && (!paused) && (offer) ) {
+                boolean result = super.offer(sc);
+                if ( result ) {
+                    size.incrementAndGet();
+                }
+                return result;
+            }
+            else return false;
+        }
+        
+        public SocketProcessor poll() {
+            SocketProcessor result = super.poll();
+            if ( result != null ) {
+                size.decrementAndGet();
+            }
+            return result;
+        }
+        
+        public void clear() {
+            super.clear();
+            size.set(0);
+        }
+    };
+
+
+    /**
      * Cache for key attachment objects
      */
     protected ConcurrentLinkedQueue<KeyAttachment> keyCache = new ConcurrentLinkedQueue<KeyAttachment>() {
@@ -727,6 +761,7 @@ public class NioEndpoint {
         eventCache.clear();
         keyCache.clear();
         nioChannels.clear();
+        processorCache.clear();
         if ( executor!=null ) {
             ThreadPoolExecutor tpe = (ThreadPoolExecutor)executor;
             tpe.shutdown();
@@ -977,19 +1012,7 @@ public class NioEndpoint {
      * Process given socket.
      */
     protected boolean processSocket(NioChannel socket) {
-        try {
-            if (executor == null) {
-                getWorkerThread().assign(socket);
-            }  else {
-                executor.execute(new SocketProcessor(socket,null));
-            }
-        } catch (Throwable t) {
-            // This means we got an OOM or similar creating a thread, or that
-            // the pool and its queue are full
-            log.error(sm.getString("endpoint.process.fail"), t);
-            return false;
-        }
-        return true;
+        return processSocket(socket,null);
     }
 
 
@@ -1001,7 +1024,10 @@ public class NioEndpoint {
             if (executor == null) {
                 getWorkerThread().assign(socket, status);
             } else {
-                executor.execute(new SocketProcessor(socket, status));
+                SocketProcessor sc = processorCache.poll();
+                if ( sc == null ) sc = new SocketProcessor(socket,status);
+                else sc.reset(socket,status);
+                executor.execute(sc);
             }
         } catch (Throwable t) {
             // This means we got an OOM or similar creating a thread, or that
@@ -1794,32 +1820,6 @@ public class NioEndpoint {
     }
 
 
-    // ---------------------------------------------- SocketOptionsProcessor Inner Class
-
-
-    /**
-     * This class is the equivalent of the Worker, but will simply use in an
-     * external Executor thread pool.
-     */
-    protected class SocketOptionsProcessor implements Runnable {
-
-        protected SocketChannel sc = null;
-
-        public SocketOptionsProcessor(SocketChannel socket) {
-            this.sc = socket;
-        }
-
-        public void run() {
-            if ( !setSocketOptions(sc) ) {
-                try {
-                    sc.socket().close();
-                    sc.close();
-                }catch ( IOException ix ) {
-                    if ( log.isDebugEnabled() ) log.debug("",ix);
-                }
-            }
-        }
-    }
     // ---------------------------------------------- SocketProcessor Inner Class
 
 
@@ -1833,6 +1833,10 @@ public class NioEndpoint {
         protected SocketStatus status = null; 
 
         public SocketProcessor(NioChannel socket, SocketStatus status) {
+            reset(socket,status);
+        }
+        
+        public void reset(NioChannel socket, SocketStatus status) {
             this.socket = socket;
             this.status = status;
         }
@@ -1850,10 +1854,11 @@ public class NioEndpoint {
                 } catch ( Exception x ) {
                     log.error("",x);
                 }
-                socket = null;
-                status = null;
             }
-
+            socket = null;
+            status = null;
+            //return to cache
+            processorCache.offer(this);
         }
 
     }
index 71c9c2c..6551834 100644 (file)
@@ -26,18 +26,29 @@ import java.net.SocketException;
  */\r
 public class SocketProperties {\r
     /**\r
-     * Enable/disable key cache, this bounced cache stores\r
+     * Enable/disable key cache, this bounded cache stores\r
      * KeyAttachment objects to reduce GC\r
-     * Default is 100\r
+     * Default is 500\r
      * -1 is unlimited\r
      * 0 is disabled\r
      */\r
     protected int keyCache = 500;\r
+    \r
+    /**\r
+     * Enable/disable socket processor cache, this bounded cache stores\r
+     * SocketProcessor objects to reduce GC\r
+     * Default is 500\r
+     * -1 is unlimited\r
+     * 0 is disabled\r
+     */\r
+    protected int processorCache = 500;\r
+\r
+\r
 \r
     /**\r
      * Enable/disable poller event cache, this bounded cache stores\r
      * PollerEvent objects to reduce GC for the poller\r
-     * Default is -1 (unlimited)\r
+     * Default is 500 \r
      * -1 is unlimited\r
      * 0 is disabled\r
      * >0 the max number of objects to keep in cache.\r
@@ -243,6 +254,10 @@ public class SocketProperties {
         return appWriteBufSize;\r
     }\r
 \r
+    public int getProcessorCache() {\r
+        return processorCache;\r
+    }\r
+\r
     public int getDirectBufferPool() {\r
         return bufferPool;\r
     }\r
@@ -327,6 +342,10 @@ public class SocketProperties {
         this.appWriteBufSize = appWriteBufSize;\r
     }\r
 \r
+    public void setProcessorCache(int processorCache) {\r
+        this.processorCache = processorCache;\r
+    }\r
+\r
     public void setDirectBufferPool(int directBufferPool) {\r
         this.bufferPool = directBufferPool;\r
     }\r
index ee9f217..e801291 100644 (file)
         The value is in bytes, the default value is 1024*1024*100 (100MB)
         </p>
       </attribute>
+      <attribute name="socket.processorCache" required="false">
+        <p>Tomcat will cache SocketProcessor objects to reduce garbage collection.
+           The integer value specifies how many objects to keep in the cache at most.
+           The default is 500.
+           Other values are -1. unlimited cache, and 0, no cache.</p>
+      </attribute>
       <attribute name="socket.keyCache" required="false">
         <p>Tomcat will cache KeyAttachment objects to reduce garbage collection.
            The integer value specifies how many objects to keep in the cache at most.