繁体   English   中英

linux在c ++中的线程之间传递高性能消息

[英]linux high performance message passing between threads in c++

说我有一个产生 2 个线程的进程

第一个线程在一个紧密循环中侦听 UDP 端口上的数据包事件。 第二个线程是接收包含在这个 UDP 数据包中的字节并解析它/做一些事情。

谁能推荐一种比使用 linux 消息队列更快的方法? 我认为它们很慢,因为它们在写入队列时复制字节并在从队列中读取时再次复制它们

我知道 zeromq 库,但有没有一种巧妙的方法来做到这一点而没有这种开销? 我意识到我可以在两个线程之间使用 tcp/ip 套接字进行简单的排队通信,但有没有更快的方法?

我在想可能是内存中的环形缓冲区在线程和用于控制指向最近更新元素的指针之间共享的互斥锁?

任何人的想法在这里?

我能想到的最有效的方法是使用一个链表、一个互斥锁和一个条件变量:

  • 线程 A:

    1. 分配一个 udp-packet-buffer 对象(该对象应该包含previousnext指针,以及一个用于存储 UDP 数据的字节数组)
    2. recv() UDP 数据到对象的字节数组
    3. 锁定互斥锁
    4. 将 udp-packet-buffer 对象附加到链表的尾部
    5. 解锁互斥锁
    6. 通知条件变量
    7. 转到 1
  • 线程 B:

    1. 等待条件变量(直到条件变量发出信号)
    2. 锁定互斥锁
    3. 从链表的头部弹出下一个 udp-packet-buffer
    4. 解锁互斥锁
    5. 解析/处理 udp-packet-buffer 对象中的 UDP 数据
    6. 删除 udp-packet-buffer 对象
    7. 转到 1

这为您提供了零拷贝通信机制。 持有互斥锁所花费的时间很少,因此争用也应该很低。

如果你想进一步优化,你可以让线程 B 一次从链表中取出所有项目,而不是一次弹出一个——这在 O(1) 时间内是可能的带有链表。 然后让线程 A 仅在链接列表在附加其最新的 udp-packet-buffer 对象之前为空时才向条件变量发出信号。 这将减少线程在重负载下必须锁定/解锁/发出信号的次数。

这个非常好的答案也是我所期望的,当来到这个页面时https://stackoverflow.com/a/8567548/2893944

一个可能有帮助的小注意事项:摆脱动态内存分配也是可以提高性能和避免内存碎片的一点(例如:使用静态数组,使用内存池)。

(这应该是一个评论,但没有足够的声誉)

结帐http://www.boost.org/libs/circular_buffer/我使用充满 boost::array<1500> 作为一个项目中 2 个线程之间的通信点,我看不出它在任何方面都很慢。 第一个线程正在接受 UDP 包,并通过检查一些位是否应该将其放入缓冲区来快速。 它确实复制进出,但在我配置文件时甚至没有显示。

编辑:BoundedBuffer 示例是有趣的位http://www.boost.org/libs/circular_buffer/doc/circular_buffer.html#boundedbuffer

为了获得最佳性能,您需要一个固定大小、无锁、单写入器、单读取器的队列。

这篇 codeproject 文章出现在一个快速的谷歌似乎合理并解释了一些来龙去脉。

我不知道您的用例是什么 - 但如果采取如此冗长的措施 - 您的软件(和环境)需要考虑如何处理由缓慢的消费者引起的队列满导致数据丢失的情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM