IPC 性能: 命名管与套接字

似乎每个人都说命名管道比套接字 IPC 快。他们的速度有多快?我更喜欢使用套接字,因为它们可以进行双向通信,而且非常灵活,但是如果速度比灵活性大得多的话,我会选择速度而不是灵活性。

131507 次浏览

命名管道和套接字在功能上是不等价的; 套接字提供了更多的特性(首先,它们是双向的)。

我们不能告诉你哪个表现更好,但我强烈怀疑这并不重要。

Unix 域套接字可以完成 tcp 套接字所能完成的工作,但是只能在本地机器上使用,并且开销(可能有点)更低。

如果 Unix 套接字速度不够快,并且要传输大量数据,可以考虑在客户机和服务器之间使用共享内存(设置起来要复杂得多)。

Unix 和 NT 都有“命名管道”,但它们在特性集上完全不同。

我建议您首先采用简单的方法,仔细地隔离 IPC 机制,这样您就可以从一个套接字切换到另一个管道,但是我肯定会首先使用套接字。 在先发制人地优化之前,您应该确保 IPC 性能是一个问题。

如果因为 IPC 速度而遇到麻烦,我认为您应该考虑切换到共享内存,而不是使用管道。

如果你想做一些传输速度测试,你应该尝试 Socat,这是一个非常通用的程序,允许你创建几乎任何类型的隧道。

我同意 shodanex 的观点,看起来你过早地试图优化一些还没有问题的东西。除非 知道套接字将成为瓶颈,否则我会直接使用它们。

许多人坚信命名管道可以节省一些费用(这取决于其他所有东西写得有多好) ,但最终代码阻塞 IPC 回复的时间比它做有用工作的时间还要长。当然,非阻塞方案对此有所帮助,但这些方案可能有些棘手。我可以说,在我看到的大多数情况下,花费数年时间将旧代码带入现代,加速几乎为零。

如果您真的认为套接字会拖慢您的速度,那么就应该开始使用共享内存,并仔细注意如何使用锁。同样,在所有的实际情况下,你可能会发现一个小的加速,但请注意,你正在浪费一部分它等待互斥锁锁。我不会提倡去 未来的地狱旅行(好吧,在2015年不再是 没错地狱,取决于你的经验)。

同等重要的是,套接字(几乎)总是最好的方式去用户空间下的 IPC 宏内核。.而且(通常)最容易调试和维护。

如果你不需要速度,插座是最简单的方式去!

如果您所关注的是速度,那么最快的解决方案是共享内存,而不是命名管道。

对于与命名管道的双向通信:

  • 如果只有几个进程,则可以打开两个方向的两个管道(processA2ProcessB 和 processB2ProcessA)
  • 如果有许多进程,则可以为每个进程(processAin、 processAout、 processBin、 processBout、 processCin、 processCout 等)打开进出管道
  • 或者你也可以像往常一样混合使用:)

命名管道很容易实现。

例如,我用命名管道在 C 语言中实现了一个项目,感谢标准的基于输入输出的通信(fopen,fprintf,fscanf...) ,它是如此简单和干净(如果这也是一个考虑因素的话)。

我甚至用 java 编写了它们(我在它们上面序列化并发送对象!)

命名管道有一个缺点:

  • 因为它们依赖于文件系统(假设不能选择共享文件系统) ,所以它们不能在多台计算机(如套接字)上进行扩展

请记住,套接字并不一定意味着 IP (以及 TCP 或 UDP)。您还可以使用 UNIX 套接字(PF _ UNIX) ,与连接到127.0.0.1相比,它提供了显著的性能改进

数字往往比感觉更能说明问题,下面是一些数据: 管道 VS Unix Socket 性能(opendmx.net)

这个基准测试显示管道的速度提高了大约12% 到15% 。

套接字的一个问题是它们没有刷新缓冲区的方法。有一种叫做 Nagle 算法的东西,它可以收集所有的数据,并在40毫秒后将其刷新。因此,如果是响应性而不是带宽,那么使用管道可能会更好。

您可以使用套接字选项 TCP _ NODELAY 禁用 Nagle,但是读取端将永远不会在一次读取调用中接收到两条短消息。

所以测试它,我最终没有得到这些,而是在共享内存中使用 pthread 互斥和信号量实现了基于内存映射的队列,避免了大量的内核系统调用(但是现在它们不再那么慢了)。

您可以使用像 ZeroMQ [ Zmq/0mq]这样的轻量级解决方案。它非常容易使用,并且比插座快得多。

使用 共享记忆解决方案获得的最佳结果。

命名管 只比 TCP 套接字好16% 。

IPC 基准测试得到的结果是:

  • 系统: Linux (Linux ubuntu 4.4.0 x86 _ 64 i7-6700K 4.00 GHz)
  • 消息: 128字节
  • 消息计数: 1000000

管道基准:

Message size:       128
Message count:      1000000
Total duration:     27367.454 ms
Average duration:   27.319 us
Minimum duration:   5.888 us
Maximum duration:   15763.712 us
Standard deviation: 26.664 us
Message rate:       36539 msg/s

FIFO (命名管道)基准:

Message size:       128
Message count:      1000000
Total duration:     38100.093 ms
Average duration:   38.025 us
Minimum duration:   6.656 us
Maximum duration:   27415.040 us
Standard deviation: 91.614 us
Message rate:       26246 msg/s

消息队列基准:

Message size:       128
Message count:      1000000
Total duration:     14723.159 ms
Average duration:   14.675 us
Minimum duration:   3.840 us
Maximum duration:   17437.184 us
Standard deviation: 53.615 us
Message rate:       67920 msg/s

共享内存基准:

Message size:       128
Message count:      1000000
Total duration:     261.650 ms
Average duration:   0.238 us
Minimum duration:   0.000 us
Maximum duration:   10092.032 us
Standard deviation: 22.095 us
Message rate:       3821893 msg/s

TCP 套接字基准:

Message size:       128
Message count:      1000000
Total duration:     44477.257 ms
Average duration:   44.391 us
Minimum duration:   11.520 us
Maximum duration:   15863.296 us
Standard deviation: 44.905 us
Message rate:       22483 msg/s

Unix 域套接字基准测试:

Message size:       128
Message count:      1000000
Total duration:     24579.846 ms
Average duration:   24.531 us
Minimum duration:   2.560 us
Maximum duration:   15932.928 us
Standard deviation: 37.854 us
Message rate:       40683 msg/s

ZeroMQ 基准:

Message size:       128
Message count:      1000000
Total duration:     64872.327 ms
Average duration:   64.808 us
Minimum duration:   23.552 us
Maximum duration:   16443.392 us
Standard deviation: 133.483 us
Message rate:       15414 msg/s

我知道这是一个超级老的线程,但它是一个重要的,所以我想加上我的0.02美元。UDS 在本地 IPC 的概念上要快得多。它们不仅速度更快,而且如果你的内存控制器支持 DMA,那么 UDS 几乎不会给你的 CPU 带来任何负载。DMA 控制器只是卸载 CPU 的内存操作。TCP 需要被打包成大小为 MTU 的块,如果你没有智能网卡或 TCP 卸载在某个特定的硬件,导致相当多的 CPU 负载。根据我的经验,在现代系统中,UDS 在延迟和吞吐量方面都要快5倍左右。

这些基准测试来自这个简单的基准测试代码。你自己试试。它还支持 UDS、管道和 TCP: https://github.com/rigtorp/ipc-bench

Local benchmarks for me

我看到一个 CPU 核心挣扎着跟上 TCP 模式,而坐在大约15% 的负载 UDS 下感谢 DMA。注意,远程 DMA 或 RDMA 在网络中获得相同的优势。

你可以在这里找到一个可以运行的长凳
enter image description here

问候