我想将可变长度消息从多个生产者传递到多个消费者,并在多插槽 Xeon E5 系统上使用低延迟队列。 (例如,400 字节且延迟为 300 纳秒就可以了。)
我寻找了使用非阻塞环形缓冲区的无锁多生产者多消费者 (MPMC) 队列的现有实现。但大多数在线实现/算法都是基于节点的(即节点是固定长度的),例如boost::lockfree::queue,midishare等
当然,有人可能会说节点类型可以设置为uint8_t
或类似的,但这样写入会很笨拙,性能也会很糟糕。
我还希望该算法能够在读者端提供覆盖检测,以便读者能够检测到数据被覆盖。
我如何实现一个队列(或其他东西)来执行此操作?
最佳答案
很抱歉回答晚了,但请查看 DPDK's Ring library 。它是免费的(BSD 许可证)、速度极快(相信您会免费找到更快的解决方案)并支持所有主要架构。还有很多例子。
to pass variable-length messages
解决方案是传递一个指向消息的指针,而不是整个消息。 DPDK 还提供memory pools library在多个线程或进程之间分配/取消分配缓冲区。内存池速度也很快,无锁,并且支持多种架构。
所以总体解决方案是:
创建内存池以在线程/进程之间共享缓冲区。每个内存池仅支持固定大小的缓冲区,因此您可能需要创建几个内存池来满足您的需求。
在线程/进程之间创建一个 MPMC 环或一组 SPSC 环对。 SPSC 解决方案可能更快,但可能不适合您的设计。
生产者分配一个缓冲区,填充它并通过环传递一个指向该缓冲区的指针。
消费者接收指针,读取消息并释放缓冲区。
听起来工作量很大,但 DPDK 内存池和环内部有很多优化。但它适合 300ns 吗?
看看官方DPDK performance reports 。虽然没有环性能的官方报告,但有 vhost/vistio 测试结果。基本上,数据包的传输方式如下:
Traffic gen. -- Host -- Virtual Machine -- Host -- Traffic gen.
主机作为一个进程运行,虚拟机作为另一个进程运行。
对于 512 字节数据包,测试结果约为每秒 4M 数据包。它不符合您的预算,但您需要做的工作要少得多......
关于c++ - 具有可变长度写入的多生产者多消费者无锁非阻塞环形缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51888483/