c++ - 具有可变长度写入的多生产者多消费者无锁非阻塞环形缓冲区

标签 c++ linux x86 lock-free circular-buffer

我想将可变长度消息从多个生产者传递到多个消费者,并在多插槽 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在多个线程或进程之间分配/取消分配缓冲区。内存池速度也很快,无锁,并且支持多种架构。

所以总体解决方案是:

  1. 创建内存池以在线程/进程之间共享缓冲区。每个内存池仅支持固定大小的缓冲区,因此您可能需要创建几个内存池来满足您的需求。

  2. 在线程/进程之间创建一个 MPMC 环或一组 SPSC 环对。 SPSC 解决方案可能更快,但可能不适合您的设计。

  3. 生产者分配一个缓冲区,填充它并通过环传递一个指向该缓冲区的指针。

  4. 消费者接收指针,读取消息并释放缓冲区。

听起来工作量很大,但 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/

相关文章:

caching - 如何在实践中创建一个 Spectre 小工具?

linux - 如何使用循环 ssh 多个服务器,但如果一个用户失败,则与两个用户尝试另一个

c++ - Dbus - 没有收到回复

assembly - VGF2P8AFFINEINVQB是最长的x86指令助记符吗?

c++ - 在更高版本的visual studio中运行vs2005 c++项目

c - 使用 fork 在进程的二叉树中进行广度优先搜索

c - 汇编代码如何确定变量在堆栈中的位置?

c++ - BLAS与CMake链接错误

c++ - 如何在所有测试用例 BOOST c++ 之后运行一个函数

c++ - 从Web服务器获取数据并发送给客户端C++