[concurrency-interest] ConcurrentLinkedQueue vs. ConcurrentLinkedDeque

Martin Buchholz martinrb at google.com
Sat Feb 27 22:44:19 EST 2016


Well done! Y'all guilted me into backporting to jdk8
https://bugs.openjdk.java.net/browse/JDK-8150780
There's even a test.

On Sat, Feb 27, 2016 at 1:47 PM, Christian Schudt
<christian.schudt at gmx.de> wrote:
> 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