On 23/09/2012 20:03, Konstantin Kolinko wrote: > 2012/9/23 <ma...@apache.org>: >> Author: markt >> Date: Sun Sep 23 15:20:38 2012 >> New Revision: 1389076 >> >> URL: http://svn.apache.org/viewvc?rev=1389076&view=rev >> Log: >> ConcurrentLinkedQueue is currently the biggest contributor to garbage in the >> load test so this is intended as a replacement. >> >> Added: >> >> tomcat/trunk/java/org/apache/tomcat/util/collections/ConcurrentStack.java >> (with props) >> tomcat/trunk/test/org/apache/tomcat/util/collections/ >> >> tomcat/trunk/test/org/apache/tomcat/util/collections/TestConcurrentStack.java >> (with props) >> >> tomcat/trunk/test/org/apache/tomcat/util/collections/TesterPerformanceConcurrentStack.java >> (with props) >> >> Added: >> tomcat/trunk/java/org/apache/tomcat/util/collections/ConcurrentStack.java >> URL: >> http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/collections/ConcurrentStack.java?rev=1389076&view=auto > >> +package org.apache.tomcat.util.collections; >> + >> +/** >> + * This is intended as a (mostly) GC-free alternative to >> + * {@link java.util.concurrent.LinkedBlockingDeque} where the requirement >> is to >> + * create a pool of re-usable objects with no requirement to shrink the >> pool. >> + * The aim is to provide the bare minimum of required functionality as >> quickly >> + * as possible with minimum garbage. >> + */ >> +public class ConcurrentStack<T> { >> + >> + private int size = 128; >> + /* >> + * Points to the next available object in the stack >> + */ >> + private int index = -1; >> + >> + private Object[] stack = new Object[size]; >> + >> + public synchronized void push(T obj) { >> + index++; >> + if (index == size) { >> + expand(); >> + } >> + stack[index] = obj; >> + } >> + >> + @SuppressWarnings("unchecked") >> + public synchronized T pop() { >> + if (index == -1) { >> + return null; >> + } >> + return (T) stack[index--]; >> + } >> + >> + private void expand() { >> + int newSize = size * 2; >> + Object[] newStack = new Object[newSize]; >> + System.arraycopy(stack, 0, newStack, 0, size); >> + // This is the only point where garbage is created by throwing away >> the >> + // old array. Note it is only the array, not the contents, that >> becomes >> + // garbage. >> + stack = newStack; >> + size = newSize; >> + } >> +} >> > > > Mismatching name. It is rather a "SynchronizedStack".
Fair enough. I'll rename. > Wouldn't its synchronized methods be a bottleneck? (That is what > ConcurrentLinkedQueue is designed to avoid). You'd think so but I am running the performance unit tests on an 8-core machine and SynchronizedStack beats ConcurrentLinkedQueue every time by a clear margin. ConcurrentLinkedQueue still uses synchronisation, just a lot less of it. SynchronizedStack beats it by only implementing exactly what is required and trading complexity for simplicity and synchronization. Also, the unit test is a worst case test in terms of contention. Real life performance will be better. There may be a switch over point with very large numbers of cores but I don't have access to a free machine with a large number of cores to test on. Hmm. people.a.o has 48 cores. There are plenty of other users but I can do some testing on there to see what the behaviour is like with a large number of threads. It is *very* slow at the minute so I may have to wait a while. I'm also keeping an eye on the overall throughput in my load test and that has remained pretty much unaffected by these changes at around 18k requests per second. > The pop() method should assign null value to the slot that it freed. Already implemented in a later commit. > (It is not important if the object is going to be re-added to the > cache. It would be noticeable if the object would be discarded, e.g. > a CharBuffer that grew too big so that we do not want to reuse it. It > would not be GC'd before the slot value is overwritten). I was prepared to live with that but not for the NIO stuff hence why it has already been fixed. Thanks for the review. Mark --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org