【问题标题】:boost::interprocess message_queue performance - rather slow?boost::interprocess message_queue 性能 - 相当慢?
【发布时间】:2011-09-06 21:58:32
【问题描述】:

我需要一个超快的 MQ 机制,发送方和接收方都用 C++ 编写,在 Windows 平台上。

我目前使用RCF-C++ 进行 IPC 的实现在 Windows 命名管道上的时钟速度约为 20,000 msg/sec。

我正在根据the demo app 测试 boost::interprocess Message Queues 的性能,并且测量到大约 48,000 条消息/秒,考虑到当我在同一设备上制作一个简单的内存映射文件通信时,这非常慢机器(在 C# 中使用 code from this blog post),我每秒收到大约 150,000 条消息。

知道为什么我从 boost message_queue 中得到如此缓慢的性能,以及我可以尝试改进它吗?

【问题讨论】:

    标签: c++ performance ipc memory-mapped-files boost-interprocess


    【解决方案1】:

    Daniel 的回答是其中的一部分,但这里有一个更大的问题:boost::interprocess 基本上将队列维护为共享内存中的一个数组,并且在发送消息时,boost::interprocess:message_queue 会进行二进制搜索根据新消息的优先级找到消息应该放在数组中的哪个位置,然后std::backward_copys 所有其他消息为其腾出空间。如果您始终使用相同的优先级,则您的消息将被放置在开头(因为它是最新的),因此您当时在缓冲区中的任何消息都将被向后复制以为其腾出空间,这需要时间。 (参见queue_free_msg 方法的实现)。

    如果您不需要消息具有优先级,而只需要一个常规的 FIFO 队列,那么这种方法比使用Circular Buffer 慢很多:插入(发送)的性能会随着队列增长。

    更新:notes on wikipedia 的帮助下,我编写了一个在内部使用循环缓冲区的 message_queue 版本,这是一个巨大的成功。

    【讨论】:

    • Omer,您可以发送使用循环缓冲区的 message_queue 版本来提升自身。他们可能会接受!
    • @Pietro 懒得这么做,但你可以在gist.github.com/3171076 看到代码 这段代码需要清理——所有提到消息优先级的内容都应该删除,新的实现完全忽略了它。
    • 我知道这已经很老了,但我正在检查是否在 boost 中使用 message_queue,我发现它现在在 boost 中(从 1.52 开始:boost.org/users/history/version_1_52_0.html,请参阅 BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX)
    【解决方案2】:

    作为 Boost 文档states,boost::interprocess::shared_memory_object 是使用 Win32 中的内存映射文件实现的。而且,boost 的消息队列也在使用那个模拟的共享内存对象。 (对于原生Win32共享内存,boost单独提供了windows_shared_memory类。)

    因此,为了获得更好的消息队列性能,您必须使用本机 Win32 共享内存对象实现自己的消息队列版本。在我的实验中,更换后性能明显提升。

    请注意,如果您更改为 Win32 本机共享内存,则必须注意“删除”共享内存。 POSIX共享内存和Win32共享内存的删除策略不同。

    【讨论】:

    • 谢谢!多哈。我现在注意到,在我的测试过程中,确实在文件系统中创建了一个文件,并用于“模拟”共享内存。您是否有机会分享您的实现,或者了解直接基于 Windows 本机共享内存的不同 C++ MQ/RPC 框架?我很难相信某处没有开箱即用的解决方案?
    • 我尝试按照您的建议更改 boost message_queue 以使用 windows_shared_memory,并对我在 google 上找到的 message_queue.hpp 进行以下编辑:(1) 替换 detail::managed_open_or_create_impl m_shmem;带有详细信息::managed_open_or_create_impl m_shmem; (2) 更改标题以包含“windows_shared_memory.hpp”而不是“shared_memory_object.hpp” (3) 注释掉 message_queue::remove 以仅返回 true;现在我看不到它在文件系统上创建文件,但性能完全一样。有什么想法吗?
    • 我觉得你的实现和我的差不多。但是性能可能取决于许多因素,例如消息的长度。除此之外,在我的测试中,使用 Win32 共享内存时打开消息队列要快得多。
    • 丹尼尔的评论很到位。两者最终都使用内存映射文件,但 windows_shared_memory 使用系统页面文件存储的文件,而不是 shared_memory_object 使用的临时常规文件。这可以让 windows_shared_memory 跳过磁盘上文件的实际创建(我想除非操作系统将您的内存分页),如果您要发送非常大的消息,这可能是一件大事;否则,即使随后的读取/写入速度与 windows_shared_memory 一样快,仅在磁盘上分配文件可能需要几秒钟/几分钟的时间
    • 从 7 年前开始,甚至还有一张公开票在提升对 windows_shared_memory 的支持到消息队列,但它似乎从未获得牵引力:svn.boost.org/trac10/ticket/7027
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-28
    • 2011-06-04
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    相关资源
    最近更新 更多