IPC性能:命名管道与套接字


114

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


10
您的里程会有所不同。:)简要介绍您预期的应用程序的典型用法,并从两者中取其好。然后,分析匿名管道,其他域和系列的套接字,信号量和共享内存或消息队列(SysV和POSIX),带有数据字的实时信号,等等。 pipe(2)(er,?mkfifo(3))可能是赢家,但直到您尝试才知道。
稻草人

2
SysV消息队列FTW!我不知道他们是否快,我只是对他们情有独钟。
汤姆·安德森

4
在这种情况下,“速度”是什么?整体数据传输率?还是延迟(第一个字节到达接收器的速度有多快)?如果您想要快速的本地数据传输,那么很难击败共享内存。但是,如果延迟是一个问题,那么这个问题将变得更加有趣...
Ian Ni-Lewis

Answers:


64

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

而且,如果由于IPC速度而遇到麻烦,我认为您应该考虑切换到共享内存,而不是通过管道传输。

如果要进行某些传输速度测试,则应尝试socat,它是一种非常通用的程序,可让您创建几乎任何类型的隧道。


47

共享内存解决方案将为您带来最佳结果。

命名管道仅比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 Queue基准测试:

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

1
感谢您提供详细的基准测试。您是将“ multiprocessing.Queue”与“消息队列”一起使用吗?
ovunccetin

1
消息队列是一个系统XSI消息队列(man7.org/linux/man-pages/man0/sys_msg.h.0p.html
chronoxor

34

我会同意shodanex,看来您过早地尝试优化尚未出现问题的产品。除非您知道套接字将成为瓶颈,否则我只会使用它们。

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

如果您确实认为套接字会降低速度,那么请使用共享内存出门,并特别注意如何使用锁。再次,实际上,您可能会发现速度有所提高,但是请注意,您浪费了一部分等待互斥锁。我不会主张一趟futex的地狱(当然,不是在2015年的地狱了,这取决于你的经验)。

一磅一磅,套接字是(几乎)始终是在单片内核下进入用户空间IPC的最佳方法,并且(通常)是最容易调试和维护的。


2
也许有一天在一个遥远的乌托邦的未来,我们将有一个全新的,模块化的,现代性的核心隐含提供了所有的(进程间等)的能力,我们现在走到破碎的玻璃来完成...但嘿..一个可以梦想
Gukki5

27

请记住,套接字不一定表示IP(以及TCP或UDP)。您还可以使用UNIX套接字(PF_UNIX),通过与127.0.0.1的连接,可以显着提高性能。


1
Windows呢?
Pacerier '17

1
@Pacerier不幸的是,您无法以与UNIX上抽象名称空间相同的方式在Windows上创建本地套接字。我发现PF_​​UNIX套接字比此页面上描述的大多数其他方法要快得多(> 10%)。
EntangledLoops

1
devblogs.microsoft.com/commandline/af_unix-comes-to-windows更新,现在Windows 10中提供了Unix套接字。
eri0o


11

如果您不需要速度,则插座是最简单的方法!

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


8

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

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

命名管道非常容易实现。

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

我什至用Java编写了代码(我正在对其进行序列化和发送对象!)

命名管道有一个缺点:

  • 它们不能像套接字一样在多台计算机上扩展,因为它们依赖于文件系统(假设不是共享文件系统)

8

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

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

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


3
“所以测试一下” <-依靠的话。
Koshinae '16

6

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

我们无法告诉您哪种会更好,但是我强烈怀疑这没关系。

Unix域套接字将执行tcp套接字的几乎所有工作,但仅在本地计算机上并且开销(可能有一点)降低。

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

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


1
好吧,如果您打开2条管道,那么您也会获得比迪烟行为。
Pacerier '17

4

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


2
您可能会喜欢Martin SUSTRIK的下一件艺术品-符合POSIX的阿米特(Amit)nanomsg。无论如何,欢迎并享受这个伟大的地方,并成为它的积极贡献会员。
user3666197
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.