基本的队列设计
|
|
这样的队列性能损耗主要是一下两点:
- 取余的计算
- volatile write以及该过程中可能发生的false sharing
因为我们探讨的OneToOne队列,那么显然volatile的刷新要求并不是很严格,可以不用每次的写操作都从cache中刷回主存
改进 - 1
|
|
优化点1
注意这里使用(int)currentTail & (capacity - 1)
优化了buffer[(int)(currentTail % capacity)] = e;
的取余操作。
不过这样的优化存在一个问题就是capacity必须是2^n
优化点2
head和tail用AtomicLong替代long
使用了lazySet来避免了频繁的volatile write在维持内存可见性时的内存损耗
改进 - 2
|
|
优化点:
使用tailCache和headCache来避免对head和tail两个AtomicLong的频繁get(),读取普通变量肯定会比Atomic快很多
实验结果
贴上参考文章中的实验结果:
Qps/Sec(Millions) | Mean Latency(ns) | |
---|---|---|
LinkedBlockingQueue | 4.3 | ~32000 / ~500 |
ArrayBlockingQueue | 3.5 | ~32000 / ~600 |
ConcurrentLinkedQueue | 13 | NA / ~180 |
ConcurrentArrayQueue | 13 | NA / ~150 |
ConcurrentArrayQueue2 | 45 | NA / ~120 |
ConcurrentArrayQueue3 | 150 | NA / ~100 |
Note: None of these tests are run with thread affinity set, Sandy Bridge 2.4 GHz Latency: Blocking - put() & take() / Non-Blocking - offer() & poll()