在 Linux 上,在 C++ 应用程序进程之间发送消息的最快技术是什么?我隐约意识到,桌面上有以下技术:
- TCP
- UDP
- 插座
- 管道
- 命名管道
- 内存映射文件
还有更多方法吗?最快的是什么?
在 Linux 上,在 C++ 应用程序进程之间发送消息的最快技术是什么?我隐约意识到,桌面上有以下技术:
还有更多方法吗?最快的是什么?
虽然上述所有答案都非常好,但我认为我们必须讨论什么是“最快”[它必须是“最快”还是“足够快”?]
对于 LARGE 消息,毫无疑问,共享内存是一种非常好的技术,并且在很多方面都非常有用。
但是,如果消息很小,则必须提出自己的消息传递协议和通知其他进程有消息的方法是有缺点的。
在这种情况下,管道和命名管道更容易使用 - 它们的行为非常像文件,您只需在发送端写入数据,然后在接收端读取数据。如果发送方写了一些东西,接收方会自动唤醒。如果管道已满,则发送端被阻塞。如果发送方没有更多数据,接收方将自动被阻止。这意味着这可以用相当少的代码行来实现,并且可以很好地保证它每次都可以正常工作。
另一方面,共享内存依赖于其他一些机制来通知另一个线程“你有一个数据包要处理”。是的,如果您要复制大量数据包,它会非常快 - 但如果管道存在巨大差异,我会感到惊讶,真的。主要好处是对方不必将数据从共享内存中复制出来——但它也依赖于有足够的内存来保存所有“正在运行”的消息,或者发送者有能力保留东西.
我不是说“不要使用共享内存”,我只是说没有“一种解决所有问题的‘最好’的解决方案”这样的东西。
澄清一下:我将首先使用管道或命名管道[取决于哪个适合目的]实现一个简单的方法,然后测量它的性能。如果实际复制数据花费大量时间,那么我会考虑使用其他方法。
当然,另一个考虑应该是“我们是否会使用两台独立的机器[或同一系统上的两台虚拟机]来解决这个问题。在这种情况下,网络解决方案是更好的选择——即使它不是最快的, 我在工作的机器上运行了一个本地 TCP 堆栈以进行基准测试,并获得了一些 20-30Gbit/s (2-3GB/s) 的持续流量。同一进程中的原始 memcpy 大约为 50-100GBit/s (5-10GB/s)(除非块大小非常小并且适合 L1 缓存)。我没有测量标准管道,但我希望这大致在这两个数字的中间。[这是数字这对于许多不同的中型相当现代的 PC 来说是正确的 - 显然,在 ARM、MIPS 或其他嵌入式控制器上,所有这些方法的数量都较低]
我建议也看看这个:How to use shared memory with Linux in C。
基本上,在单台机器上进行 IPC 时,我会放弃 TCP 和 UDP 等网络协议。这些具有分组开销并且绑定到更多资源(例如端口、环回接口)。
英国剑桥大学的 NetOS 系统研究小组已经完成了一些(开源)IPC 基准测试。
源代码位于https://github.com/avsm/ipc-bench。
项目页面:http ://www.cl.cam.ac.uk/research/srg/netos/projects/ipc-bench/ 。
结果:http ://www.cl.cam.ac.uk/research/srg/netos/projects/ipc-bench/results.html
本研究已使用上述结果发表:http: //anil.recoil.org/papers/drafts/2012-usenix-ipc-draft1.pdf
检查 CMA 和 kdbus: https ://lwn.net/Articles/466304/
我认为这些天最快的东西是基于 AIO。 http://www.kegel.com/c10k.html
当你用 C++ 标记这个问题时,我推荐Boost.Interprocess:
共享内存是最快的进程间通信机制。操作系统将一个内存段映射到多个进程的地址空间中,这样多个进程就可以在该内存段中读写,而无需调用操作系统函数。但是,我们需要在读取和写入共享内存的进程之间进行某种同步。
我发现的一个警告是同步原语的可移植性限制。例如,OS X 和 Windows 都没有进程间条件变量的本机实现,因此它使用自旋锁来模拟它们。
现在,如果您使用支持 POSIX 进程共享原语的 *nix,则不会有任何问题。
当涉及大量数据时,具有同步的共享内存是一种很好的方法。
好吧,您可以使用linux shared memory aka在您的进程之间简单地拥有一个共享内存段SHM
。
它非常易于使用,请查看链接以获取一些示例。
posix 消息队列非常快,但它们有一些限制