145

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

4

11 回答 11

90

使用共享内存解决方案可获得最佳结果。

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

通过IPC 基准测试获得结果:

  • 系统:Linux(Linux ubuntu 4.4.0 x86_64 i7-6700K 4.00GHz)
  • 消息: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
于 2019-01-12T21:32:26.253 回答
73

我建议你先走简单的路,仔细隔离 IPC 机制,以便你可以从套接字更改为管道,但我肯定会先使用套接字。在抢先优化之前,您应该确定 IPC 性能是一个问题。

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

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

于 2009-08-06T13:17:07.270 回答
36

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

许多对命名管道发誓的人发现了一些节省(取决于其他所有内容的编写情况),但最终得到的代码花费更多的时间阻止 IPC 回复而不是做有用的工作。当然,非阻塞方案对此有所帮助,但这些可能很棘手。我可以说,花费数年时间将旧代码带入现代时代,在我见过的大多数情况下,加速几乎为零。

如果您真的认为套接字会拖慢您的速度,那么请立即使用共享内存,并注意您如何使用锁。同样,实际上,您可能会发现一个小的加速,但请注意您浪费了一部分等待互斥锁。我不会提倡去futex 地狱之旅(嗯, 2015 年不再是地狱,这取决于你的经验)。

以磅为重,套接字(几乎)总是在单片内核下实现用户空间 IPC 的最佳方式......并且(通常)最容易调试和维护。

于 2009-08-07T17:52:31.573 回答
29

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

于 2011-07-22T02:34:14.640 回答
28

通常,数字比感觉更重要,这里有一些数据: Pipe vs Unix Socket Performance (opendmx.net)

该基准显示管道的速度提高了大约 12% 到 15%。

于 2013-03-24T20:24:07.873 回答
11

如果您不需要速度,套接字是最简单的方法!

如果您正在查看的是速度,那么最快的解决方案是共享内存,而不是命名管道。

于 2009-12-23T20:55:44.267 回答
9

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

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

所以测试它,我最终什么都没有,并在共享内存中使用 pthread 互斥锁和信号量实现了基于内存映射的队列,避免了很多内核系统调用(但今天它们不再很慢了)。

于 2015-06-20T15:44:49.053 回答
8

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

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

命名管道很容易实现。

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

我什至用 java 对它们进行了编码(我正在序列化并通过它们发送对象!)

命名管道有一个缺点:

  • 它们不能像套接字一样在多台计算机上扩展,因为它们依赖于文件系统(假设共享文件系统不是一个选项)
于 2010-09-21T17:28:16.633 回答
8

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

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

Unix 域套接字几乎可以完成 tcp 套接字的工作,但仅在本地机器上并且(可能有点)较低的开销。

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

Unix 和 NT 都有“命名管道”,但它们的功能集完全不同。

于 2009-08-06T07:26:11.680 回答
5

您可以使用 ZeroMQ [ zmq/0mq ] 之类的轻量级解决方案。它非常易于使用,并且比套接字快得多。

于 2017-04-01T23:31:51.287 回答
3

I know this is a super old thread but it's an important one so I'd like to add my $0.02. UDS are much faster in concept for local IPC. Not only are they faster but if your memory controller supports DMA then UDS causes almost no load on your CPU. The DMA controller will just offload memory operations for the CPU. TCP needs to be packetized into chunks of size MTU and if you don't have a smart nic or TCP offload somewhere in specialized hardware that causes quite a bit of load on the CPU. In my experiences UDS are around 5x faster on modern systems in both latency and throughput.

These benchmarks come from this simple benchmark code. Try for yourself. It also supports UDS, pipes, and TCP: https://github.com/rigtorp/ipc-bench

Local benchmarks for me

I see a CPU core struggling to keep up with TCP mode while sitting at about ~15% load under UDS thanks to DMA. Note that Remote DMA or RDMA gains the same advantages in a network.

于 2021-07-02T08:06:32.157 回答