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 ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/collections/ConcurrentStack.java (added) +++ tomcat/trunk/java/org/apache/tomcat/util/collections/ConcurrentStack.java Sun Sep 23 15:20:38 2012 @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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; + } +} Propchange: tomcat/trunk/java/org/apache/tomcat/util/collections/ConcurrentStack.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/trunk/test/org/apache/tomcat/util/collections/TestConcurrentStack.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/collections/TestConcurrentStack.java?rev=1389076&view=auto ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/collections/TestConcurrentStack.java (added) +++ tomcat/trunk/test/org/apache/tomcat/util/collections/TestConcurrentStack.java Sun Sep 23 15:20:38 2012 @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.collections; + +import org.junit.Assert; +import org.junit.Test; + +public class TestConcurrentStack { + + @Test + public void testPopEmpty() { + ConcurrentStack<Object> stack = new ConcurrentStack<>(); + Assert.assertNull(stack.pop()); + } + + @Test + public void testPushPopOrder() { + ConcurrentStack<Object> stack = new ConcurrentStack<>(); + + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + Object o4 = new Object(); + + stack.push(o1); + stack.push(o2); + stack.push(o3); + stack.push(o4); + + Assert.assertSame(stack.pop(), o4); + Assert.assertSame(stack.pop(), o3); + Assert.assertSame(stack.pop(), o2); + Assert.assertSame(stack.pop(), o1); + + Assert.assertNull(stack.pop()); + } + + @Test + public void testExpandPushPopOrder() { + ConcurrentStack<Object> stack = new ConcurrentStack<>(); + + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + Object o4 = new Object(); + + for (int i = 0; i < 300; i++) { + stack.push(o1); + stack.push(o2); + stack.push(o3); + stack.push(o4); + } + + for (int i = 0; i < 300; i++) { + Assert.assertSame(stack.pop(), o4); + Assert.assertSame(stack.pop(), o3); + Assert.assertSame(stack.pop(), o2); + Assert.assertSame(stack.pop(), o1); + } + + Assert.assertNull(stack.pop()); + } + +} Propchange: tomcat/trunk/test/org/apache/tomcat/util/collections/TestConcurrentStack.java ------------------------------------------------------------------------------ svn:eol-style = native Added: tomcat/trunk/test/org/apache/tomcat/util/collections/TesterPerformanceConcurrentStack.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/collections/TesterPerformanceConcurrentStack.java?rev=1389076&view=auto ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/util/collections/TesterPerformanceConcurrentStack.java (added) +++ tomcat/trunk/test/org/apache/tomcat/util/collections/TesterPerformanceConcurrentStack.java Sun Sep 23 15:20:38 2012 @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.collections; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.junit.Test; + +public class TesterPerformanceConcurrentStack { + + private static final int THREAD_COUNT = 8; + private static final int ITERATIONS = 1000000; + + private static final ConcurrentStack<Object> STACK = + new ConcurrentStack<>(); + + private static final Queue<Object> QUEUE = new ConcurrentLinkedQueue<>(); + + @Test + public void testConcurrentStack() throws InterruptedException { + Thread[] threads = new Thread[THREAD_COUNT]; + for (int i = 0; i < THREAD_COUNT; i++) { + threads[i] = new StackThread(); + } + + long start = System.currentTimeMillis(); + + for (int i = 0; i < THREAD_COUNT; i++) { + threads[i].start(); + } + + for (int i = 0; i < THREAD_COUNT; i++) { + threads[i].join(); + } + + long end = System.currentTimeMillis(); + + System.out.println("ConcurrentStack: " + (end - start) + "ms"); + } + + public static class StackThread extends Thread { + + @Override + public void run() { + for(int i = 0; i < ITERATIONS; i++) { + Object obj = STACK.pop(); + if (obj == null) { + obj = new Object(); + } + STACK.push(obj); + } + super.run(); + } + } + + @Test + public void testConcurrentQueue() throws InterruptedException { + Thread[] threads = new Thread[THREAD_COUNT]; + for (int i = 0; i < THREAD_COUNT; i++) { + threads[i] = new QueueThread(); + } + + long start = System.currentTimeMillis(); + + for (int i = 0; i < THREAD_COUNT; i++) { + threads[i].start(); + } + + for (int i = 0; i < THREAD_COUNT; i++) { + threads[i].join(); + } + + long end = System.currentTimeMillis(); + + System.out.println("ConcurrentLinkedQueue: " + (end - start) + "ms"); + } + + public static class QueueThread extends Thread { + + @Override + public void run() { + for(int i = 0; i < ITERATIONS; i++) { + Object obj = QUEUE.poll(); + if (obj == null) { + obj = new Object(); + } + QUEUE.add(obj); + } + super.run(); + } + } +} Propchange: tomcat/trunk/test/org/apache/tomcat/util/collections/TesterPerformanceConcurrentStack.java ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org