并发队列(concurrentqueue) 总结篇(还有显式生产者没有分析)

138 阅读2分钟

这篇文章主要就是总结,为什么这个项目的效率那么的高、速度那么的快.它优秀设计的点在哪里
先给出作者的性能测试图,让你震撼一下它的效率

AWS 8-Core机器 image.png

image.png

image.png

AWS 32-core机器 image.png

image.png

image.png

通过对比就可以看到,concurrentqueue它的曲线很平稳.相比于其他的并发队列,陡降特别明显.

效率高的点

1. 分块设计

使用"块"来管理数据而不是直接操作整个数组.使得每个生产者线程都有属于自己的块,避免多个线程共用一个数据结构,导致竞争效率下降.

2. 最小CAS操作

  • 传统的队列需要频繁使用 CAS(Compare-And-Swap)来保护 headtail 操作,而 ConcurrentQueue 尽量将 CAS 操作集中在少数关键的入队和出队操作上
  • 通过分块和适当的分配/回收机制,队列在每个块的起点和终点才进行 CAS 操作,其余操作在内存中的局部范围内是安全的,因此减少了 CAS 操作带来的性能开销

3. 低内存争用

  • 直接操作数组中的 headtail 指针会导致大量线程争用这些指针,特别是在高并发下。ConcurrentQueue 使用了局部缓冲区(缓存)来减少线程之间的相互依赖
  • 当多个线程操作同一个队列时,这些局部缓存允许每个线程暂时在自己的缓存里入队或出队数据,然后合并到共享队列中,减少对全局队列指针的争用

4. 轻量级的内存分配

  • 对于内存管理,ConcurrentQueue 使用了内存池(Memory Pool),预分配了多个块,并在需要时复用这些块。相比于直接分配和释放数组的元素,这样的内存池设计减少了频繁的内存分配和回收,提高了效率
  • 内存池配合回收机制有效降低了垃圾回收和内存分配的负担,使得队列在高并发下也能保持稳定的性能

5. 缓存友好的数据结构

  • ConcurrentQueue 的分块设计和数据布局有助于提高缓存命中率。每个块的大小设计合理,使其能很好地适应 CPU 缓存的大小,减少内存访问时的缓存缺失问题,从而降低了延迟
  • 使用内存对齐优化和缓存友好的访问模式,使得在同一块内的数据操作能够更高效地被 CPU 缓存优化处理