操作系统中的内存膨胀


13

一些虚拟机管理程序使用一种称为“膨胀”的方法(至少是KVM所谓的“膨胀”)来优化内存使用,该方法对VM之间的内存进行重复数据删除,并将普通页面设置为只读,并在写入时进行复制。
这与fork调用相反。

在操作系统级别上实现流程是否可行(我主要想到的是在同一站点上使用带有多个选项卡的Chromium浏览时重复存储),是否已经实现?

Answers:


14

实际上,您所描述的内容使膨胀和“同一页面合并”混淆了。我将尝试详细说明两者,以使区别显而易见。

内存膨胀

这是一个技巧,可确保分配给来宾虚拟机的某些内存仍可被另一个来宾主机本身(缓存等)使用。可以通过以下方式完成:

来宾内核注入了一个驱动程序,该驱动程序监视来宾内存使用情况,并“窃取”一些未使用的内存(将其分配给来宾内存空间,以确保该来宾服务器上的任何内容都无法触及该范围)。

然后,它通知主机内核,实际上它可以从内核中删除这些内存页面,它们将不会在guest虚拟机中使用(直到guest虚拟机遇到一定的内存压力,此时气球将收缩并使用这些范围再次)。

最终,内核可以将完全相同的内存分配给另一个来宾,如果来宾使用大量可用内存运行,可以使整个内存使用效率更高。

同一页合并

这项技术可以识别相同的内存页面,由于某种原因,它们尚未被写时复制标记为“准只读”,并对其进行了标记。

现在,在OS级别上,对这些技巧的需求有限。简而言之,在大多数情况下,当您具有相同的内存页时,它们已经是只读的(有时甚至没有CoW),因为它们大多是应用程序代码,库等。它们是通过内存映射本机打开的,因此内核可以保持它们只有一个副本在核心中(如果有的话,它也可以完全将其分页出来,并允许根据需要从主存储分页)。

在虚拟OS级别上,每个来宾子系统内正确应用了相同的原理。但是,主机内核不知道两个来宾系统是否大多数都在运行相同的代码,从而共享相同的内存-来宾系统无法进行通信来协调。

这就是为什么它有时会扫描整个系统完全相同的内存页-大部分的时间,他们将是相同的客户操作系统的,不是每一个内-客户内核做一个体面的工作,使记忆它的范围内整齐。因此,在一个主机内核处理50个以上来宾的典型VM环境中,可以节省大量内存。

两者都一次

膨胀和同一页合并可以很好地共存,从而为相同系统实现了相当大的内存过量使用。


要回答您的问题-有时可以在操作系统级别启用“同页面合并”。它与被解释的页面共享有关,因此最终可能是相同的,而没有相同的后备文件。

在您的Chromium示例中-进程二进制文件本身已经通过只读启动映射进行了重复数据删除-它们共享完全相同的内存空间。由于管理磁盘缓存的方式,页面缓存(选项卡的内容)通常也在进程之间共享(只读复制时复制)-可以在虚拟机中的不同进程之间模拟地打开同一磁盘文件-最佳感觉。

在不同Javascript引擎的共享状态下,优势最为明显-但我不确定它们是否分配在完全相同的内存布局中,以确保整个内存页面都是相同的。

在移动系统上这是不同的。例如,Android广泛采用KSM对不同应用程序之间的相同代码进行重复数据删除。

无论哪种情况,都可以在Linux上自己启用它(内核SamePage合并)。驱动程序导出各种统计信息,在阅读此答案之后,您应该能够进行解释,并自行决定是否适合您的目的。

https://www.kernel.org/doc/Documentation/vm/ksm.txt


3
取决于管理程序(及其使用期限),同一页合并也称为“超验内存”。
蒂姆·波斯特

谢谢,我看到KSM要求应用程序知道它,并且从(快速)搜索开始,Chromium目前不支持它。我知道二进制文件已进行重复数据删除,但是我主要是指JIT输出和原始脚本,这些脚本给我的RAM带来了沉重的负担……

Chromium中的原始脚本也已进行重复数据删除-与所有其他Web对象一样,它们位于磁盘缓存中,并且磁盘缓存已映射而不是读取。
qdot 2014年

原始脚本被映射,但是即使是常见的脚本(如jQuery和Angular.js)也被复制到缓存中,并且它们彼此不匹配,因为在各种站点服务器上大量使用了CDN和脚本文件的精确副本。

这可能最终应该在聊天中,但是我很想从Linux的KSM中查看您的统计信息。
qdot 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.