Author: fhanik Date: Wed Oct 25 15:11:10 2006 New Revision: 467787 URL: http://svn.apache.org/viewvc?view=rev&rev=467787 Log: Documented socket properties Added in the ability to cache bytebuffers based on number of channels or number of bytes Added in nonGC poller events to lower CPU usage during high traffic
Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java?view=diff&rev=467787&r1=467786&r2=467787 ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioChannel.java Wed Oct 25 15:11:10 2006 @@ -55,6 +55,14 @@ bufHandler.getReadBuffer().clear(); bufHandler.getWriteBuffer().clear(); } + + public int getBufferSize() { + if ( bufHandler == null ) return 0; + int size = 0; + size += bufHandler.getReadBuffer()!=null?bufHandler.getReadBuffer().capacity():0; + size += bufHandler.getWriteBuffer()!=null?bufHandler.getWriteBuffer().capacity():0; + return size; + } /** * returns true if the network buffer has Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?view=diff&rev=467787&r1=467786&r2=467787 ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Wed Oct 25 15:11:10 2006 @@ -47,6 +47,7 @@ import org.apache.tomcat.util.net.SecureNioChannel.ApplicationBufferHandler; import org.apache.tomcat.util.res.StringManager; import org.apache.tomcat.util.net.NioEndpoint.KeyAttachment; +import java.util.concurrent.atomic.AtomicInteger; /** * NIO tailored thread pool, providing the following services: @@ -150,6 +151,8 @@ protected ConcurrentLinkedQueue<NioChannel> nioChannels = new ConcurrentLinkedQueue<NioChannel>() { + protected AtomicInteger size = new AtomicInteger(0); + protected AtomicInteger bytes = new AtomicInteger(0); public boolean offer(NioChannel socket) { Poller pol = socket.getPoller(); Selector sel = pol!=null?pol.getSelector():null; @@ -157,13 +160,32 @@ KeyAttachment att = key!=null?(KeyAttachment)key.attachment():null; if ( att!=null ) att.reset(); if ( key!=null ) key.attach(null); + boolean offer = socketProperties.getBufferPool()==-1?true:size.get()<socketProperties.getBufferPool(); + offer = offer && (socketProperties.getBufferPoolSize()==-1?true:(bytes.get()+socket.getBufferSize())<socketProperties.getBufferPoolSize()); //avoid over growing our cache or add after we have stopped - if ( running && (!paused) && (size() < socketProperties.getDirectBufferPool()) ) return super.offer(socket); + if ( running && (!paused) && (offer) ) { + boolean result = super.offer(socket); + if ( result ) { + size.incrementAndGet(); + bytes.addAndGet(socket.getBufferSize()); + } + return result; + } else return false; } public NioChannel poll() { - return super.poll(); + NioChannel result = super.poll(); + if ( result != null ) { + size.decrementAndGet(); + bytes.addAndGet(-result.getBufferSize()); + } + return result; + } + + public void clear() { + super.clear(); + size.set(0); } }; @@ -940,16 +962,62 @@ } - // ----------------------------------------------------- Poller Inner Class - + // ----------------------------------------------------- Poller Inner Classes /** + * + * PollerEvent, cacheable object for poller events to avoid GC + */ + public class PollerEvent implements Runnable { + protected NioChannel socket; + protected int interestOps; + public PollerEvent(NioChannel ch, int intOps) { + reset(ch, intOps); + } + + public void reset(NioChannel ch, int intOps) { + socket = ch; + interestOps = intOps; + } + + public void reset() { + reset(null, 0); + } + + public void run() { + final SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); + final KeyAttachment att = (KeyAttachment) key.attachment(); + try { + if (key != null) { + key.interestOps(interestOps); + att.interestOps(interestOps); + } + } + catch (CancelledKeyException ckx) { + try { + if (key != null && key.attachment() != null) { + KeyAttachment ka = (KeyAttachment) key.attachment(); + ka.setError(true); //set to collect this socket immediately + } + try { + socket.close(); + } + catch (Exception ignore) {} + if (socket.isOpen()) + socket.close(true); + } + catch (Exception ignore) {} + } + } + } + /** * Poller class. */ public class Poller implements Runnable { protected Selector selector; - protected ConcurrentLinkedQueue events = new ConcurrentLinkedQueue(); + protected ConcurrentLinkedQueue<Runnable> events = new ConcurrentLinkedQueue<Runnable>(); + protected ConcurrentLinkedQueue<PollerEvent> eventCache = new ConcurrentLinkedQueue<PollerEvent>(); protected boolean close = false; protected long nextExpiration = 0;//optimize expiration handling @@ -1000,30 +1068,15 @@ * @param socket to add to the poller */ public void add(final NioChannel socket) { - final SelectionKey key = socket.getIOChannel().keyFor(selector); - final KeyAttachment att = (KeyAttachment)key.attachment(); - Runnable r = new Runnable() { - public void run() { - try { - if (key != null) { - key.interestOps(SelectionKey.OP_READ); - att.interestOps(SelectionKey.OP_READ); - } - }catch ( CancelledKeyException ckx ) { - try { - if ( key != null && key.attachment() != null ) { - KeyAttachment ka = (KeyAttachment)key.attachment(); - ka.setError(true); //set to collect this socket immediately - } - try {socket.close();}catch (Exception ignore){} - if ( socket.isOpen() ) socket.close(true); - } catch ( Exception ignore ) {} - } - } - }; + add(socket,SelectionKey.OP_READ); + } + + public void add(final NioChannel socket, final int interestOps) { + PollerEvent r = this.eventCache.poll(); + if ( r==null) r = new PollerEvent(socket,interestOps); addEvent(r); } - + public boolean events() { boolean result = false; //synchronized (events) { @@ -1032,6 +1085,10 @@ while ( (r = (Runnable)events.poll()) != null ) { try { r.run(); + if ( r instanceof PollerEvent ) { + ((PollerEvent)r).reset(); + eventCache.offer((PollerEvent)r); + } } catch ( Exception x ) { log.error("",x); } @@ -1049,7 +1106,6 @@ Runnable r = new Runnable() { public void run() { try { - socket.getIOChannel().register(selector, SelectionKey.OP_READ, ka); } catch (Exception x) { log.error("", x); @@ -1398,25 +1454,7 @@ final SelectionKey fk = key; final int intops = handshake; final KeyAttachment ka = (KeyAttachment)fk.attachment(); - //register for handshake ops - Runnable r = new Runnable() { - public void run() { - try { - fk.interestOps(intops); - ka.interestOps(intops); - } catch (CancelledKeyException ckx) { - try { - if ( fk != null && fk.attachment() != null ) { - ka.setError(true); //set to collect this socket immediately - try {ka.getChannel().getIOChannel().socket().close();}catch(Exception ignore){} - try {ka.getChannel().close();}catch(Exception ignore){} - } - } catch (Exception ignore) {} - } - - } - }; - ka.getPoller().addEvent(r); + ka.getPoller().add(socket,intops); } } } finally { Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?view=diff&rev=467787&r1=467786&r2=467787 ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Wed Oct 25 15:11:10 2006 @@ -68,8 +68,15 @@ //initiate handshake sslEngine.beginHandshake(); initHandshakeStatus = sslEngine.getHandshakeStatus(); - } + + public int getBufferSize() { + int size = super.getBufferSize(); + size += netInBuffer!=null?netInBuffer.capacity():0; + size += netOutBuffer!=null?netOutBuffer.capacity():0; + return size; + } + //=========================================================================================== // NIO SSL METHODS Modified: tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java?view=diff&rev=467787&r1=467786&r2=467787 ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/tomcat/util/net/SocketProperties.java Wed Oct 25 15:11:10 2006 @@ -4,21 +4,92 @@ import java.net.SocketException; public class SocketProperties { + /** + * Enable/disable direct buffers for the network buffers + * Default value is enabled + */ protected boolean directBuffer = true; + /** + * Socket receive buffer size in bytes (SO_RCVBUF) + * Default value is 25188 + */ protected int rxBufSize = 25188; + /** + * Socket send buffer size in bytes (SO_SNDBUF) + * Default value is 43800 + */ protected int txBufSize = 43800; - protected int directBufferPool = 500; + /** + * NioChannel pool size for the endpoint, + * this value is how many channels + * -1 means unlimited cached, 0 means no cache + * Default value is 500 + */ + protected int bufferPool = 500; + + + /** + * Buffer pool size in bytes to be cached + * -1 means unlimited, 0 means no cache + * Default value is 100MB (1024*1024*100 bytes) + */ + protected int bufferPoolSize = 1024*1024*100; + + /** + * TCP_NO_DELAY option, default is false + */ protected boolean tcpNoDelay = false; + /** + * SO_KEEPALIVE option, default is false + */ protected boolean soKeepAlive = false; + /** + * OOBINLINE option, default is true + */ protected boolean ooBInline = true; + /** + * SO_REUSEADDR option, default is true + */ protected boolean soReuseAddress = true; + /** + * SO_LINGER option, default is true, paired with the <code>soLingerTime</code> value + */ protected boolean soLingerOn = true; + /** + * SO_LINGER option, default is 25 seconds. + */ protected int soLingerTime = 25; + /** + * SO_TIMEOUT option, default is 5000 milliseconds + */ protected int soTimeout = 5000; + /** + * Traffic class option, value between 0 and 255 + * IPTOS_LOWCOST (0x02) + * IPTOS_RELIABILITY (0x04) + * IPTOS_THROUGHPUT (0x08) + * IPTOS_LOWDELAY (0x10) + * Default value is 0x04 | 0x08 | 0x010 + */ protected int soTrafficClass = 0x04 | 0x08 | 0x010; + /** + * Performance preferences according to + * http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#setPerformancePreferences(int,%20int,%20int) + * Default value is 1 + */ protected int performanceConnectionTime = 1; + /** + * Performance preferences according to + * http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#setPerformancePreferences(int,%20int,%20int) + * Default value is 0 + */ protected int performanceLatency = 0; + /** + * Performance preferences according to + * http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#setPerformancePreferences(int,%20int,%20int) + * Default value is 1 + */ protected int performanceBandwidth = 1; @@ -91,8 +162,16 @@ return txBufSize; } + public int getBufferPool() { + return bufferPool; + } + + public int getBufferPoolSize() { + return bufferPoolSize; + } + public int getDirectBufferPool() { - return directBufferPool; + return bufferPool; } public void setPerformanceConnectionTime(int performanceConnectionTime) { @@ -151,8 +230,16 @@ this.soLingerOn = soLingerOn; } + public void setBufferPool(int bufferPool) { + this.bufferPool = bufferPool; + } + + public void setBufferPoolSize(int bufferPoolSize) { + this.bufferPoolSize = bufferPoolSize; + } + public void setDirectBufferPool(int directBufferPool) { - this.directBufferPool = directBufferPool; + this.bufferPool = directBufferPool; } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]