每个人似乎都说命名管道比套接字IPC更快。他们快多快了?我更喜欢使用套接字,因为它们可以进行双向通信,并且非常灵活,但如果数量相当大,则选择速度超过灵活性。
答案 0 :(得分:55)
我建议你首先采取简单的路径,小心地隔离ipc机制,以便你可以从套接字更改为管道,但我肯定会首先使用套接字。 在抢先优化之前,您应该确保IPC性能是一个问题。
如果因为IPC速度而遇到麻烦,我认为你应该考虑切换到共享内存,而不是去管道。
如果你想进行一些传输速度测试,你应该尝试socat,这是一个非常通用的程序,可以让你创建几乎任何类型的隧道。
答案 1 :(得分:30)
我会同意shodanex,看起来你过早地试图优化那些尚未出现问题的东西。除非你知道套接字将成为瓶颈,否则我只会使用它们。
很多发誓命名管道的人都会节省一些钱(取决于其他所有内容的编写方式),但最终会得到的代码花费更多的时间来阻止IPC回复而不是做有用的工作。当然,非阻塞方案对此有所帮助,但这些可能很棘手。我可以说,花费数年时间将旧代码带入现代,在我见过的大多数情况下,加速几乎为零。
如果你真的认为套接字会降低你的速度,那么请使用共享内存走出大门,注意如何使用锁。同样,在所有情况下,您可能会发现一个小的加速,但请注意,您正在浪费其中的一部分等待互斥锁。我不会主张去futex hell旅行(好吧,在2015年不再相当地狱,取决于你的经验)。
英镑,套接字(几乎)总是在单片内核下用户空间IPC的最佳方式..并且(通常)最容易调试和维护。
答案 2 :(得分:26)
请记住,套接字并不一定意味着IP(以及TCP或UDP)。您还可以使用UNIX套接字(PF_UNIX),与连接到127.0.0.1相比,它提供了显着的性能提升
答案 3 :(得分:26)
通常情况下,数字不只是感觉,这里有一些数据: Pipe vs Unix Socket Performance (opendmx.net)
此基准测试显示管道速度差异大约12至15%。
答案 4 :(得分:13)
使用共享内存解决方案可获得的最佳结果。
命名管道仅比 TCP套接字好16%。
通过IPC benchmarking获得结果:
管道基准:
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
答案 5 :(得分:10)
如果您不需要速度,插座是最简单的方法!
如果您关注的是速度,最快的解决方案是共享内存,而不是命名管道。
答案 6 :(得分:8)
用于与命名管道的双向通信:
命名管道非常容易实现。
E.g。我使用命名管道在C中实现了一个项目,这要归功于基于标准文件输入输出的通信(fopen,fprintf,fscanf ...)它非常简单和干净(如果这也是一个考虑因素)。
我甚至用java编码它们(我正在序列化并通过它们发送对象!)
命名管道有一个缺点:
答案 7 :(得分:7)
套接字的一个问题是它们没有办法刷新缓冲区。有一种称为Nagle算法的东西可以收集所有数据并在40ms后刷新它。因此,如果它是响应性而不是带宽,那么使用管道可能会更好。
您可以使用套接字选项TCP_NODELAY禁用Nagle,但是在一次单个读取调用中,读取端将永远不会收到两条短消息。
所以测试它,我最终没有这个,并在共享内存中使用pthread互斥和信号量实现了基于内存映射的队列,避免了很多内核系统调用(但今天它们不再是非常慢)。
答案 8 :(得分:6)
命名管道和插座在功能上并不相同;套接字提供了更多功能(它们是双向的,一开始)。
我们无法告诉你哪个会表现得更好,但我强烈怀疑它并不重要。
Unix域套接字将完成tcp套接字的功能,但只能在本地机器上运行,并且(可能会有点)开销较低。
如果Unix套接字不够快并且您要传输大量数据,请考虑在客户端和服务器之间使用共享内存(设置起来要复杂得多)。
Unix和NT都有“命名管道”,但它们在功能集上完全不同。
答案 9 :(得分:3)
您可以使用ZeroMQ [zmq/0mq]等轻量级解决方案。它非常易于使用,并且比插座快得多。
答案 10 :(得分:2)
我知道这是一个非常古老的话题,但它很重要,所以我想添加我的 0.02 美元。对于本地 IPC,UDS 在概念上要快得多。它们不仅速度更快,而且如果您的内存控制器支持 DMA,那么 UDS 几乎不会对您的 CPU 造成负载。 DMA 控制器只会卸载 CPU 的内存操作。 TCP 需要打包成大小为 MTU 的块,并且如果您在专用硬件中的某处没有智能 nic 或 TCP 卸载会导致 CPU 上的相当多的负载。根据我的经验,UDS 在现代系统上的延迟和吞吐量提高了大约 5 倍。
这些基准测试来自这个简单的基准测试代码。自己试试。它还支持 UDS、管道和 TCP:https://github.com/rigtorp/ipc-bench
由于 DMA,我看到 CPU 内核在 UDS 下以大约 15% 的负载努力跟上 TCP 模式。请注意,远程 DMA 或 RDMA 在网络中具有相同的优势。