gpt4 book ai didi

linux - IPC共享内存和线程内存的性能差异

转载 作者:太空狗 更新时间:2023-10-29 12:39:09 25 4
gpt4 key购买 nike

我经常听说,与在线程之间访问进程内存相比,在进程之间访问共享内存段不会造成性能损失。换句话说,多线程应用程序不会比一组使用共享内存的进程更快(不包括锁定或其他同步问题)。

但我有疑问:

1) shmat() 将本地进程虚拟内存映射到共享段。必须为每个共享内存地址执行此转换,并且可能代表巨大的成本。在多线程应用程序中,不需要额外的转换:所有 VM 地址都转换为物理地址,就像在不访问共享内存的常规进程中一样。

2) 共享内存段必须由内核以某种方式维护。例如,当所有连接到 shm 的进程都被关闭时,shm 段仍然在运行并且最终可以被新启动的进程重新访问。可能会有一些与 shm 段上的内核操作相关的开销。

多进程共享内存系统和多线程应用程序一样快吗?

最佳答案

1) shmat() maps the local process virtual memory to the shared segment. This translation has to be performed for each shared memory address and can represent a significant cost, relative to the number of shm accesses. In a multi-threaded application there is no extra translation required: all VM addresses are converted to physical addresses, as in a regular process that does not access shared memory.

除了设置共享页面的初始成本之外,与常规内存访问相比没有任何开销 - 在调用 shmat() 的进程中填充页表 - 在大多数 Linux 版本中每 4KB 共享内存 1 页(4 或 8 字节)。

无论页面是共享分配的还是在同一进程中分配的(对于所有相关比较),成本都是相同的。

2) The shared memory segment must be maintained somehow by the kernel. I do not know what that 'somehow' means in terms of performances, but for example, when all processes attached to the shm are taken down, the shm segment is still up and can be eventually re-accessed by newly started processes. There must be at least some degree of overhead related to the things the kernel needs to check during the lifetime of the shm segment.

无论是否共享,内存的每一页都有一个“结构页”附加到它上面,其中包含关于该页的一些数据。其中一项是引用计数。当页面被分配给进程时[无论是通过“shmat”还是其他机制],引用计数都会增加。当它通过某种方式被释放时,引用计数就会减少。如果递减计数为零,则该页面实际上已被释放 - 否则“它不会再发生任何事情”。

与分配的任何其他内存相比,开销基本上为零。无论如何,相同的机制用于页面的其他目的 - 例如你有一个页面也被内核使用 - 并且你的进程死了,内核需要知道在它被内核释放之前不要释放该页面以及用户进程。

创建“fork”时也会发生同样的事情。当一个进程被 fork 时,父进程的整个页表基本上被复制到子进程中,并且所有页面都变成只读的。每当发生写入时,内核都会发生错误,导致该页面被复制 - 因此现在该页面有两个副本,并且进行写入的进程可以修改它的页面,而不会影响其他进程。一旦子(或父)进程死亡,当然所有页面仍由两个进程拥有 [例如从未被写入的代码空间,可能还有一堆从未被触及的公共(public)数据等] 显然不能释放直到两个进程都“死了”。再次强调,引用计数页面在这里很有用,因为我们只对每个页面的引用计数进行倒计时,当引用计数为零时——也就是说,当所有使用该页面的进程都释放了它时——该页面是实际上作为“有用的页面”返回。

完全相同的事情发生在共享库上。如果一个进程使用一个共享库,它会在该进程结束时被释放。但是,如果两个、三个或 100 个进程使用同一个共享库,代码显然必须保留在内存中,直到不再需要页面为止。

所以,基本上,整个内核中的所有页面都已经被引用计数了。开销很小。

关于linux - IPC共享内存和线程内存的性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55497324/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com