IPC性能:命名管道与插座

use*_*745 98 sockets linux performance ipc named-pipes

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

sho*_*nex 58

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

如果你因为IPC的速度而遇到麻烦,我认为你应该考虑切换到共享内存,而不是去管道.

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

  • 为socat +1,之前没见过 (2认同)

Tim*_*ost 31

我将同意shodanex,看起来你过早地试图优化那些尚未出现问题的东西.除非你知道套接字将成为瓶颈,否则我只是使用它们.

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

如果你真的认为套接字会降低你的速度,那么请使用共享内存走出大门,注意如何使用锁.同样,在所有情况下,您可能会发现一个小的加速,但请注意,您正在浪费其中一部分等待互斥锁.我不会主张一趟futex的地狱(当然,不是在2015年的地狱了,这取决于你的经验).

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

  • 也许在遥远的乌托邦式的未来的某一天,我们将拥有一个全新的,模块化的,现代的内核,它隐式地提供了我们目前在碎玻璃上行走以完成的所有(进程间和其他)功能……但是,嘿。 (2认同)

Hib*_*u57 27

通常,数字不只是感觉,这里有一些数据: 管道与Unix套接字性能(opendmx.net).

该基准测试显示管道速度差异大约12至15%.


Yul*_*liy 26

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

  • https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/更新,Unix套接字现在在Windows 10中可用。 (3认同)

chr*_*xor 20

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

命名管道仅比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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

共享内存基准测试:

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • “只有 16%”:-) 如果您拥有一百万台服务器并且您是支付电费的人,那么 16% 就已经是巨大的数字了。而且,128 字节也小得不切实际。 (3认同)
  • 命名管道与简单进程启动和参数传递相比有多少? (2认同)

pla*_*ank 14

你可以在这里找到一个可运行的工作台https://github.com/goldsborough/ipc-bench
在此输入图像描述

问候


Dam*_*ien 10

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

如果您正在考虑的是速度,最快的解决方案是共享内存,而不是命名管道.


Boe*_*Boy 9

我知道这是一个非常旧的线程,但它很重要,所以我想添加我的 0.02 美元。从概念上讲,UDS 对于本地 IPC 来说要快得多。它们不仅速度更快,而且如果您的内存控制器支持 DMA,那么 UDS 几乎不会对您的 CPU 造成任何负载。DMA 控制器只会卸载 CPU 的内存操作。TCP 需要被打包成 MTU 大小的块,如果您没有智能网卡或专用硬件中的 TCP 卸载,则会对 CPU 造成相当大的负载。根据我的经验,UDS 在现代系统上的延迟和吞吐量都快了 5 倍左右。

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

我的本地基准

我看到 CPU 核心在 UDS 下由于 DMA 而处于大约 15% 的负载时,正在努力跟上 TCP 模式。请注意,远程 DMA 或 RDMA 在网络中具有相同的优势。


dag*_*han 8

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

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

命名管道很容易实现.

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

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

命名管道有一个缺点:

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


Lot*_*har 8

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

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

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

  • “所以测试一下” <-依靠的话。 (2认同)

Mar*_*rkR 6

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

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

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

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

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

  • 好吧,如果你打开 2 个管道,那么你也会得到比迪烟的行为。 (2认同)

Ami*_*jic 5

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

  • 你可能会喜欢,猜猜 Amit,Martin SUSTRIK 的下一个艺术作品——符合 POSIX 的**`nanomsg`**。无论如何,欢迎并享受这个好地方并成为它的积极贡献成员。 (2认同)