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

时间:2011-12-19 20:33:35

标签: c++ linux performance messaging

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

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

任何人都可以推荐比使用linux消息队列更快的方法吗? 我认为它们很慢,因为它们在写入队列时复制字节并在从队列中读取时再次复制它们

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

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

任何想法在这里?

4 个答案:

答案 0 :(得分:5)

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

Thread A:
   1. Allocate a udp-packet-buffer object (the object should contain 'previous' and 'next' pointers, and an array of bytes to store UDP data in)
   2. recv() UDP data into the object's byte-array
   3. lock the mutex
   4. append the udp-packet-buffer object to tail of the linked-list
   5. unlock the mutex
   6. signal the condition variable
   7. goto 1

Thread B:
   1. wait on the condition variable (until the condition variable is signaled)
   2. lock the mutex
   3. pop the next udp-packet-buffer off the head of the linked-list
   4. unlock the mutex
   5. parse/handle the UDP data in the udp-packet-buffer object
   6. delete the udp-packet-buffer object
   7. goto 1

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

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

结帐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

答案 3 :(得分:0)

为获得最佳性能,您需要固定大小的lockess,单写入器,单读取器队列。

This codeproject article出现在一个快速谷歌似乎合理,并解释了一些细节。

我不知道你的用例是什么 - 但是如果采取这么长的措施 - 你的软件(和环境)需要考虑如何处理慢速消费者造成的完整队列会导致数据损失的情况。 / p>