boost::interprocess message_queue 性能 - 相当慢?
我需要一个超快的 MQ 机制,发送方和接收方都是在 Windows 平台上用 C++ 编写的。
我当前使用 RCF-C++ 进行 IPC 的实现速度约为 20,000 条消息/秒通过 Windows 命名管道。
我正在根据 演示应用程序,测量到每秒大约 48,000 条消息,考虑到当我在同一台计算机上编写一个简单的内存映射文件通信时(在 C# 中使用 < a href="http://techmikael.blogspot.com/2010/02/blazing-fast-ipc-in-net-4-wcf-vs.html" rel="noreferrer">此博客文章中的代码),我每秒收到大约 150,000 条消息。
知道为什么我的 boost message_queue 性能如此缓慢,以及我可以尝试如何改进它吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Daniel的答案是其中的一部分,但这里有一个更大的问题:boost::interprocess基本上将队列维护为共享内存中的数组,并且在发送消息时,boost::interprocess:message_queue基于新消息的优先级来查找该消息应放置在数组中的位置,然后 std::backward_copy 存储所有其他消息为其腾出空间。如果您始终使用相同的优先级,您的消息将被放置在开头(因为它是最新的),因此当时缓冲区中的任何消息都将被向后复制以为它腾出空间,这需要时间。 (请参阅
queue_free_msg
方法的实现)。如果您不需要消息具有优先级,而只想要一个常规的 FIFO 队列,那么这种方法比使用 Circular 慢很多Buffer:插入(发送)的性能随着队列大小的增长而迅速恶化。
更新:我在维基百科上的注释的帮助下编写了一个在内部使用循环缓冲区的message_queue版本,这是一个巨大的成功。
Daniel's answer is part of it, but there is a bigger issue here: boost::interprocess basically maintains the queue as an array in shared memory, and upon sending a message, the boost::interprocess:message_queue does a binary search based on the new message's priority to find where the message should be placed in the array, and then
std::backward_copy
s all the other messages to make room for it. If you always use the same priority, your message will be placed at the beginning (since it's the newest), and so whatever messages you have in the buffer at that time will be backwards_copied to make room for it, which takes time. (See implementation of thequeue_free_msg
method).If you don't need messages to have priorities, and just want a regular FIFO queue, then this approach is a lot slower than using a Circular Buffer: the performance of insertions (sends) deteriorates rapidly as the size of the queue grows.
UPDATE: I wrote a version of the message_queue that uses a circular buffer internally, with help from the notes on wikipedia, and this was a big success.
正如Boost文档所述、boost::interprocess::shared_memory_object是在Win32中使用内存映射文件实现的。而且,boost 的消息队列也使用模拟的共享内存对象。 (对于本机Win32共享内存,boost单独提供了windows_shared_memory类。)
因此,为了使消息队列有更好的性能,您必须使用本机Win32共享内存对象实现您自己版本的消息队列。在我的实验中,更换它后,性能显着提高。
请注意,如果更改为 Win32 本机共享内存,则必须注意共享内存的“删除”。 POSIX共享内存和Win32共享内存有不同的删除策略。
As Boost document states, boost::interprocess::shared_memory_object is implemented using memory mapped file in Win32. And, boost's message queue is using that simulated shared memory object as well. (For native Win32 shared memory, boost provides windows_shared_memory class separately.)
For better performance of message queue, therefore, you have to implement your own version of message queue using native Win32 shared memory object. In my experiments, after replacing it, performance increased noticeably.
Note that, if you change to Win32 native shared memory, you must take care of 'deletion' of the shared memory. POSIX shared memory and Win32 shared memory has different policy of deletion.