【问题标题】:UNIX Domain sockets vs Shared Memory (Mapped File)UNIX 域套接字与共享内存(映射文件)
【发布时间】:2021-07-29 17:26:10
【问题描述】:

谁能告诉我,与共享内存(或替代内存映射文件)相比,UNIX 域套接字有多慢?

谢谢。

【问题讨论】:

    标签: unix memory sockets


    【解决方案1】:

    这更多的是设计问题,而不是速度(共享内存更快),域套接字绝对是 UNIX 风格的,并且做的问题要少得多。在选择方面事先知道:

    域套接字的优势

    • 阻塞和非阻塞模式以及它们之间的切换
    • 您不必在任务完成后释放它们

    域套接字的缺点

    • 必须以线性方式读写

    共享内存优势

    • 非线性存储
    • 永远不会阻止
    • 多个程序可以访问它

    共享内存的缺点

    • 需要锁定实现
    • 需要手动释放,即使没有被任何程序使用

    这就是我现在能想到的。但是,我每天都会使用域套接字——更不用说重新实现它们来进行分布式计算要容易得多。由于需要安全的设计,共享内存的速度增益将丢失。但是,如果您确切知道自己在做什么,并使用正确的内核调用,您可以通过共享内存实现更快的速度。

    【讨论】:

    • 感谢详细解答和比较!
    • need manual freeing, even if unused by any program可以和/dev/ashmem对战
    【解决方案2】:

    在速度方面共享内存绝对是赢家。使用套接字,您将拥有至少两个数据副本——从发送进程到内核缓冲区,然后从内核到接收进程。使用共享内存,延迟将仅受盒子上内核之间的缓存一致性算法的约束。

    不过,正如 Kornel 所指出的,处理共享内存更复杂,因为您必须提出自己的同步/信令方案,这可能会增加延迟,具体取决于您走的路线。一定要在共享内存中使用信号量(在 Linux 上用futex 实现)以避免非竞争情况下的系统调用。

    【讨论】:

    • 我相信 Unix 域套接字与普通套接字的区别在于一端的写入直接进入另一端的接收缓冲区。所以不一定有额外的副本。如果您能找到一种方法让应用程序在共享内存中实际使用同一个对象而不是将其复制出来,那么这可能仍然比所需的副本多。
    • 至少有两个额外的副本——从用户到内核,然后再返回。
    • 这不是只有在超过 512 个字节时才成立吗? (Linux 上为 4096 字节)
    【解决方案3】:

    两者都是进程间通信 (IPC) 机制。 UNIX 域套接字用于一台主机上的进程之间的通信,类似于在不同主机之间使用 TCP 套接字。 共享内存 (SHM) 是一块内存,您可以在其中放置数据并在进程之间共享。 SHM 通过使用指针为您提供随机访问,可以写入或读取套接字,但您不能倒带或定位。

    【讨论】:

      【解决方案4】:

      @Kornel Kisielewicz 的回答是很好的 IMO。只需在此处为套接字添加我自己的结果,而不仅仅是 Unix 域套接字。

      共享内存

      • 性能非常高。没有带有 RAW 访问数据的副本。肯定是最快的访问。
      • 需要同步。复杂情况下的设计并不容易设置。
      • 固定大小。 Growing shared memory is doable 但内存必须先取消映射、增长,然后重新映射。
      • 信号机制可能很慢,请参阅此处:Boost.Interprocess notify() performance。特别是如果您想在进程之间进行大量交换。信号机制也不太容易设置。

      套接字

      • 易于设置。
      • 可以在不同的机器上使用。
      • 无需复杂的同步。
      • 如果使用 TCP,大小不是问题。简单的设计,头部包含数据包大小,然后发送数据。
      • Ping/Pong 交换速度很快,因为它可以被操作系统视为硬件中断。
      • 性能一般:制作了几份数据。
      • 与共享内存相比,CPU 消耗较高。如果您经常使用 Socket 调用,它们的成本并不低。

      在我的测试中,小块数据(大约 1MByte/秒)的交换显示共享内存没有真正的优势。我什至会说使用 TCP 的 ping/pong 交换更快(由于简单而有效的信号机制)。 但是在交换大量数据(大约 200MBytes/秒)时,我使用套接字的 CPU 消耗为 20%,而使用共享内存的 CPU 消耗为 3%。所以在 CPU 方面共享内存是一个巨大的胜利,因为readwrite 套接字调用并不便宜。

      【讨论】:

        【解决方案5】:

        在这种情况下 - 套接字更快。写入共享内存比任何 IPC 都快,但是写入内存映射文件和写入共享内存是完全不同的两件事。

        在写入内存映射文件时,您需要将写入共享内存的内容“刷新”到实际的绑定文件(不完全是,正在为您完成刷新),因此您首先将数据复制到共享内存,然后你将它再次复制(刷新)到实际文件中,这是超级膨胀的 - 比任何东西都多,甚至比写入套接字还要多,这样做你一无所获。

        【讨论】:

        • 这不是真的。通过内存映射文件(这是正常机制)设置共享内存相对简单,并且数据共享以快速方式发生。
        • 另外,为了防止混淆,mmaped 文件存在于内存中而不是物理磁盘上,并且没有物理磁盘机制及其相关驱动程序创建的相同性能限制。只有在使用持久化映射文件时,数据才会写入磁盘。
        猜你喜欢
        • 2011-01-16
        • 1970-01-01
        • 2014-11-07
        • 2014-02-20
        • 2010-11-10
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        • 2023-04-06
        相关资源
        最近更新 更多