【问题标题】:IPC performance: Named Pipe vs SocketIPC 性能:命名管道与套接字
【发布时间】:2010-11-17 04:23:14
【问题描述】:

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

【问题讨论】:

  • 您的里程会有所不同。 :) 为您的预期应用程序描述典型用途,并选择两者中的更好者。然后分析匿名管道、其他域和系列的套接字、信号量和共享内存或消息队列(SysV 和 POSIX)、带有数据字的实时信号或其他。 pipe(2)(呃,mkfifo(3)?)可能是赢家,但只有你尝试过才能知道。
  • SysV 消息队列 FTW!我不知道他们是否很快,我只是对他们情有独钟。
  • 在这种情况下什么是“速度”?整体数据传输率?还是延迟(第一个字节到达接收器的速度有多快)?如果您想要快速的本地数据传输,那么很难击败共享内存。但是,如果延迟是一个问题,那么这个问题就会变得更有趣......

标签: linux performance sockets ipc named-pipes


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      使用IPC benchmarking获取结果:

      • 系统: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
      

      【讨论】:

      • 感谢您提供详细的基准测试。你的意思是“multiprocessing.Queue”和“Message Queue”吗?
      • Message Queue 是系统 XSI 消息队列 (man7.org/linux/man-pages/man0/sys_msg.h.0p.html)
      • "只有 16 %" :-) 如果您拥有一百万台服务器并且您是支付电费的人,那么 16% 是巨大的。此外,128 字节小得不切实际。
      • 命名管道与简单的进程启动和参数传递相比有多少?
      【解决方案4】:

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

      【讨论】:

      • 您可能会喜欢,Amit,Martin SUSTRIK 的下一部作品——符合 POSIX nanomsg。无论如何,欢迎并享受这个伟大的地方并成为它的积极贡献成员。
      【解决方案5】:

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

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

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

      【讨论】:

      • “所以测试一下”
      【解决方案6】:

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

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

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

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

      【讨论】:

      • 也许在遥远的乌托邦未来的某一天,我们将拥有一个全新的、模块化的、现代的内核,它隐含地提供了我们目前走过碎玻璃来完成的所有(进程间和其他)能力......但是,嘿..一个人可以梦想
      【解决方案7】:

      通常,数字比感觉更能说明问题,这里有一些数据: Pipe vs Unix Socket Performance (opendmx.net).

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

      【讨论】:

        【解决方案8】:

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

        【讨论】:

        • Windows 怎么样?
        • @Pacerier 遗憾的是,您不能像在 UNIX 上创建抽象命名空间那样在 Windows 上创建本地套接字。我发现 PF_UNIX 套接字比本页描述的大多数其他方法要快得多(>10%)。
        • devblogs.microsoft.com/commandline/af_unix-comes-to-windows 更新,Unix 套接字现在在 Windows 10 中可用。
        【解决方案9】:

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

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

        命名管道很容易实现。

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

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

        命名管道有一个缺点:

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

        【讨论】:

          【解决方案10】:

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

          如果你看的是速度,最快的解决方案是共享内存,而不是命名管道。

          【讨论】:

            【解决方案11】:

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

            我们无法告诉您哪个性能更好,但我强烈怀疑这无关紧要。

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

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

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

            【讨论】:

            • 好吧,如果你打开 2 个管道,那么你也会得到 bidi 行为。
            猜你喜欢
            • 2021-09-21
            • 2010-12-17
            • 1970-01-01
            • 1970-01-01
            • 2010-12-25
            • 1970-01-01
            • 2012-06-08
            • 2011-03-05
            • 1970-01-01
            相关资源
            最近更新 更多