[concurrency-interest] ConcurrentLinkedQueue vs. ConcurrentLinkedDeque

Christian Schudt christian.schudt at gmx.de
Sat Feb 27 16:47:34 EST 2016


Hi,

thanks for proving :-)

Do you think it’s fairly safe to assume, that the OOM issue (JDK-8054446) is also the cause for a high CPU usage?

We use CLQ in a simple LRU cache implementation, where a remove() happens every time an element is added to or get from cache (in order to rearrange elements for the least-recently-used logic). After a few hours/days our app has very high CPU, maybe because the remove() takes longer and longer…

This seems to be the same issue:
https://issues.apache.org/jira/browse/AMQ-5337

Ok, even when it’s fixed in JDK 9, when would you use a CLQ over a CLDeque? Is it „only“ to save 40% performance when only needing a queue? (of course still worth it). Maybe the public JavaDoc should mention it.

Best,
Christian


> Am 27.02.2016 um 15:00 schrieb Haim Yadid <haim at performize-it.com>:
> 
> Hi Martin 
> I wrote a simple JMH benchmark to prove it.
> When using ConcurrenLinkedQueue without your fix at JDK-8054446 it is extremely slow your fix solves the problem 
> Here are the results :
> 
> Benchmark                          Mode  Cnt         Score         Error                 Units
> QBench.measureABQ           thrpt    5  17031943.831 ± 8468127.395  ops/s
> QBench.measureCLD           thrpt    5  15410606.543 ±  551687.064  ops/s
> QBench.measureCLQFixed  thrpt    5  27674624.318 ± 1849425.328  ops/s
> QBench.measureCLQOrig    thrpt    5      5527.394 ±    2371.913        ops/s
> 
> Here is the code :
> 
> 
> 
> 
> import org.openjdk.jmh.annotations.Benchmark;
> import org.openjdk.jmh.annotations.BenchmarkMode;
> import org.openjdk.jmh.annotations.Fork;
> import org.openjdk.jmh.annotations.Measurement;
> import org.openjdk.jmh.annotations.Mode;
> import org.openjdk.jmh.annotations.Scope;
> import org.openjdk.jmh.annotations.Setup;
> import org.openjdk.jmh.annotations.State;
> import org.openjdk.jmh.annotations.Threads;
> import org.openjdk.jmh.annotations.Warmup;
> 
> import java.util.Queue;
> import java.util.concurrent.ArrayBlockingQueue;
> import java.util.concurrent.ConcurrentLinkedDeque;
> 
> import java.util.concurrent.ExecutionException;
> 
> 
> @Fork(1)
> @Threads(1)
> @BenchmarkMode({Mode.Throughput})
> @Warmup(iterations = 5)
> @Measurement(iterations = 5)
> public class QBench {
>   static final String a = "a";
>   static final String b = "b";
>   public static final int NUM_PRE = 1;
>   @State(Scope.Benchmark)
>   public static class ArrayBlockingQueueState {
>     Queue<String> queue = new ArrayBlockingQueue<String>(1000);
>     @Setup
>     public void setup() throws ExecutionException, InterruptedException {
>       for(int i=0;i<NUM_PRE;i++) queue.offer(a);
>     }
>   }
>   @Benchmark
>   public Object measureABQ(final ArrayBlockingQueueState arrayBlockingQueueState) throws Exception {
>     Queue queue = arrayBlockingQueueState.queue;
>     queue.offer(b);
>     return queue.remove(b);
> 
>   }
> 
> 
> 
>   @State(Scope.Benchmark)
>   public static class ConcurrentLinkedDequeState {
>     Queue<String> queue = new ConcurrentLinkedDeque<>();
>     @Setup
>     public void setup() throws ExecutionException, InterruptedException {
>       for(int i=0;i<NUM_PRE;i++) queue.offer(a);
>     }
>   }
>   @Benchmark
>   public Object measureCLD(final ConcurrentLinkedDequeState concurrentLinkedDequeState) throws Exception {
>     Queue queue = concurrentLinkedDequeState.queue;
>     queue.offer(b);
>     return  queue.remove(b);
>   }
> 
> 
>   @State(Scope.Benchmark)
>   public static class ConcurrentLinkedQueueState {
>     Queue<String> queue = new ConcurrentLinkedQueue<>();
>     @Setup
>     public void setup() throws ExecutionException, InterruptedException {
>       for(int i=0;i<NUM_PRE;i++) queue.offer(a);
>     }
>   }
> 
>   @Benchmark
>   public Object measureCLQFixed(final ConcurrentLinkedQueueState concurrentLinkedQueueState) throws Exception {
>     Queue queue = concurrentLinkedQueueState.queue;
>     queue.offer(b);
>     return queue.remove(b);
>   }
> 
>   @State(Scope.Benchmark)
>   public static class ConcurrentLinkedQueueOrigState {
>     Queue<String> queue = new java.util.concurrent.ConcurrentLinkedQueue<>();
>     @Setup
>     public void setup() throws ExecutionException, InterruptedException {
>       for(int i=0;i<NUM_PRE;i++) queue.offer(a);
>     }
>   }
> 
>   @Benchmark
>   public Object measureCLQOrig(final ConcurrentLinkedQueueOrigState state) throws Exception {
>     Queue queue = state.queue;
>     queue.offer(b);
>     return queue.remove(b);
>   }
> }
> 
> On Fri, Feb 26, 2016 at 7:14 PM, Martin Buchholz <martinrb at google.com> wrote:
> Seems very likely.  You could try to prove it...
> 
> On Fri, Feb 26, 2016 at 9:04 AM, Christian Schudt
> <christian.schudt at gmx.de> wrote:
> > I’ve seen that. Is that also the reason for the worse performance?
> 
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> 
> 
> 
> -- 
> Haim Yadid | Performization Expert 
> Performize-IT | t +972-54-7777132
> www.performize-it.com




More information about the Concurrency-interest mailing list