【发布时间】:2015-04-11 16:55:32
【问题描述】:
Linux有copy-on-write,也就是说,在fork之后,只要不修改子进程,子进程就可以和父进程共享内存。
假设父进程占用 10 GB 的物理 RAM。当我 fork 进程时,操作系统使用的物理内存不会立即增加 10 GB(由于创建了一些管理结构,它可能会略有增加)。这可以使用free shell 命令来确认。因此free 正确解释了 CoW。
但是,当我向操作系统询问特定进程使用的内存量(例如,使用top 或我知道的任何 C API 函数)时,它表明子进程使用的物理内存是立即 10 GB(在它修改任何内容之前)。因此,每个进程的内存跟踪函数不能正确解释 CoW。
我正在寻找一种方法来衡量 CoW 的每个进程的内存占。 (打算从python中使用它,但是一旦我知道了相关的C API,我就没事了。)
澄清一下:多个进程使用的共享内存应该分配给父进程,以便记账。
用例:
我们正在尝试减少应用程序使用的总内存。我们在父进程中有非常大的数据结构,通过简单的分叉与子进程共享。我们不需要在子进程中修改这些结构,但是对引用计数器的修改(在 python 中)会导致部分内存被复制。我们正在努力尽量减少这种情况发生的程度,以保留物理内存。
相关问题
https://serverfault.com/questions/676335/how-measure-memory-without-copy-on-write-pages(提供可能的答案)
How to know whether a copy-on-write page is an actual copy?(提供一些有用的细节来创建解决方案)
【问题讨论】:
-
两个进程的虚拟页面映射到相同的物理页面; “谁拥有物理记忆”没有明确的答案......
-
对于哪个进程拥有内存的自然定义是,父进程拥有共享内存,因为它在子进程启动之前已经被使用。这将为子进程分配(几乎)零内存,直到它实际开始修改它。在某些情况下,此定义可能没有用,但在最明显的情况下,这可以帮助分析和改善内存使用情况。
-
这是个好主意,但实际上没有任何东西可以跟踪它。
-
我不认为担心谁“拥有”内存是有生产力的——而是关注找出哪些页面映射到多个进程,哪些没有。有什么方法可以在 fork 测试之前将某些页面设置为只读?如果您的代码尝试写入它们,这可能会导致保护错误,从而至少在您的测试覆盖路径的范围内让您了解这些情况。您可以使用仅从一侧读取的进程间共享内存而不是分叉后的写时复制行为以某种方式重新工作吗?
-
看起来你真正想做的是将数据分组在一个地方,除了它的元数据(例如引用计数)在另一个地方,这样前者可以保留在许多未修改的地方页面和后面的页面集中在一些修改的页面上。也许改变结构的大小(更少的更大的,内部手动区分)可能会有所帮助。一个真正的解决方案是修改 python 以使用不同的分配器存储两个类别,但这将是一个大项目。
标签: linux ubuntu memory linux-kernel