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>() {
eventCache.clear();
keyCache.clear();
nioChannels.clear();
+ processorCache.clear();
if ( executor!=null ) {
ThreadPoolExecutor tpe = (ThreadPoolExecutor)executor;
tpe.shutdown();
* 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);
}
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
}
- // ---------------------------------------------- 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
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;
}
} catch ( Exception x ) {
log.error("",x);
}
- socket = null;
- status = null;
}
-
+ socket = null;
+ status = null;
+ //return to cache
+ processorCache.offer(this);
}
}
*/\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
return appWriteBufSize;\r
}\r
\r
+ public int getProcessorCache() {\r
+ return processorCache;\r
+ }\r
+\r
public int getDirectBufferPool() {\r
return bufferPool;\r
}\r
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
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.