4

我一直在阅读 Linux 的“swappiness”可调参数,它控制内核在不使用时将应用程序的内存交换到磁盘的积极程度。如果你用谷歌搜索这个词,你会看到很多这样的页面讨论优缺点。简而言之,论点是这样的:

如果您的 swappiness 太低,不活动的应用程序将占用其他程序可能想要使用的所有系统内存。

如果您的 swappiness 太高,当您唤醒那些不活动的应用程序时,将会有很大的延迟,因为它们的状态会从磁盘读回。

这个论点对我来说没有意义。如果我有一个使用大量内存的非活动应用程序,为什么内核不将其内存分页到磁盘并将该数据的另一个副本留在内存中?这似乎是两全其美:如果另一个应用程序需要该内存,它可以立即申请物理 RAM 并开始对其进行写入,因为它的另一个副本在磁盘上,并且可以在不活动的应用程序被唤醒时换回向上。当原始应用程序唤醒时,它的任何仍在 RAM 中的页面都可以按原样使用,而无需将它们从磁盘中拉出。

还是我错过了什么?

4

4 回答 4

3

如果我有一个使用大量内存的非活动应用程序,为什么内核不将其内存分页到磁盘并将该数据的另一个副本留在内存中?

可以说我们做到了。我们将页面写入磁盘,但将其留在内存中。过了一会儿,另一个进程需要内存,所以我们想从第一个进程中踢出页面。

我们需要绝对确定地知道第一个进程是否在页面被写入磁盘后对其进行了修改。如果有,我们必须重新写出来。我们跟踪这一点的方法是在我们第一次将其写入磁盘时将进程对页面的写权限带回。如果该进程再次尝试写入该页面,则会出现页面错误。在恢复写权限并允许应用程序继续之前,内核可以注意到该进程已经弄脏了页面(因此需要再次写出)。

问题就在于此。从页面中删除写权限实际上有点昂贵,尤其是在多处理器机器中。重要的是,所有 CPU 都清除其页面翻译缓存以确保它们取消写入权限。

如果进程确实写入页面,则发生页面错误会更加昂贵。我认为这些页面中的重要数量最终会承担这个错误,这会通过将其留在内存中来侵蚀我们正在寻找的收益。

那么值得做吗?老实说,我不知道。我只是想解释为什么将页面留在内存中并不像听起来那么明显。

(*) 这整个事情非常类似于一种称为 Copy-On-Write 的机制,它在进程 fork()s 时使用。子进程很可能只执行几条指令并调用 exec(),因此复制所有父页面会很愚蠢。取而代之的是,写权限被取消,孩子只是允许运行。Copy-On-Write 是一个胜利,因为几乎从未发生页面错误:孩子几乎总是立即调用 exec()。

于 2008-09-29T02:12:44.097 回答
1

即使您将应用程序内存分页到磁盘并将其保存在内存中,您仍然必须决定何时应将应用程序视为“非活动”,这就是交换性控制的内容。分页到磁盘在 IO 方面是昂贵的,您不想经常这样做。这个等式还有另一个变量,那就是 Linux 使用剩余内存作为磁盘缓冲区/缓存的事实。

于 2008-09-29T01:05:02.107 回答
0

根据这个1这正是 Linux 所做的。

我仍在尝试理解其中的很多内容,因此任何权威链接都将不胜感激。

于 2009-02-04T16:57:09.167 回答
0

VM 做的第一件事是清理页面并将它们移动到清理列表中。
清理匿名内存时(没有实际文件后备存储的东西,您可以在 /proc//maps 中看到匿名的段,并且它们后面没有文件系统 vnode 存储),VM 要做的第一件事是取“脏”页面和“干净”页面,然后将页面内容写入交换。现在,当虚拟机缺少完全空闲的内存并且担心它是否能够授予新的空闲页面以供使用时,它可以通过“干净”页面的列表并根据它们最近的使用时间和内存类型它们会将这些页面移动到空闲列表中。

一旦内存页面被放置在空闲列表中,它们就不再与之前的内容相关联。如果一个程序引用了该页面先前服务的内存位置,则该程序将发生重大故障,并且将从空闲列表中抓取一个(很可能完全不同的)页面,并将数据从磁盘读入该页面。一旦完成,页面实际上仍然是“干净的”,因为它没有被修改过。如果 VM 选择在交换时使用该页面以换取 RAM 中的不同页面,则该页面将再次“脏”,或者如果应用程序写入该页面,它将被“脏”。然后该过程再次开始。

此外,对于业务/事务/在线/延迟敏感环境中的服务器应用程序,swappinness 非常可怕。当我有 16GB 的 RAM 盒子时,我没有运行很多浏览器和 GUI,我通常希望我的所有应用程序几乎都固定在内存中。我的大部分 RAM 往往是 8-10GB Java 堆,我从来没有想要分页到磁盘,永远,可用的垃圾是像mingetty这样的进程(但即使在那里,这些应用程序中的glibc页面也被其他应用程序共享并实际使用,因此即使是那些无用进程的RSS大小也大多是共享的,使用页)。我通常不会看到超过几个 10MB 的 16GB 实际清理以进行交换。我建议服务器的交换数量非常非常低或为零 - 未使用的页面应该是整个 RAM 的一小部分,并且试图回收相对少量的 RAM 用于缓冲区缓存可能会交换应用程序页面并导致延迟命中正在运行的应用程序。

于 2009-07-29T18:20:10.777 回答