为什么当我还有未使用的 RAM 时,部分交换空间却被使用了?

为什么当我还有未使用的 RAM 时,部分交换空间却被使用了?

这更多的是一种好奇而不是一个问题;而且,我承认,这是一个令人尴尬的基本问题:

我注意到,在很多情况下,在我的 Linux 机器上,我会有大约 500MB 的交换空间在被使用,尽管我有大约 600MB 的未使用的 RAM。

我天真的高层理解是,直到 RAM 耗尽时,交换空间才会启动。

我进一步假设这种情况一定是 Linux 内核造成的,因为请求内存的用户进程只是在逻辑上这样做,并且不知道该内存实际上是由 RAM 还是交换空间物理支持的。

这就引出了一个问题:为什么内核会抢先使用交换空间?这是某种性能调优算法的一部分吗?它是否将其认为最不可能被访问的内存部分交换到磁盘(也许是 LRU 方案)?如果是这样,那么将所有内容留在 RAM 中,只有当接近耗尽时,才将 LRU 部分从 RAM 交换到交换空间,这不是更合理吗?

我应该澄清一下,我的 Linux 服务器有 2GB 的 RAM 和 2GB 的交换空间。

答案1

没用过部分 RAM 实际上用作 HDD 缓存。如果您仔细想想,您实际上读取磁盘部分的频率要高于访问 RAM 部分的频率。将 RAM 放在磁盘上,同时使用 RAM 缓存 HDD 数据,这样做是有道理的。

答案2

提前交换东西是有意义的,因为当您真正需要内存时,您不必等到内核完成磁盘访问。

例如,假设您要打开一个大图像。加载图像时,需要 300MB 的 RAM。如果内核使用了所有可用的 RAM,则加载图像需要内核将 200MB 的 RAM 传输到磁盘。如果它事先主动清空 RAM,则可以节省几毫秒。

答案3

两个原因:

  1. (@dtrosset) Linux 将交换程序中未使用的位以提供更多的缓存和缓冲区。
  2. 您可能在过去使用了更多的内存,并换出了一些东西,而它还没有被换入,因为它还没有被使用,尽管强制它换出的任何东西现在已经消失了。

答案4

除了其他答案之外,您还可以配置 Linux 以要求支持任何分配的内存,即使程序不使用它。

然而,过度使用内存和担心 OOM 杀手并不是 Linux 体验的必要部分。只需将 sysctl 参数 vm/overcommit_memory 设置为 2,即可关闭过度使用行为并永远阻止 OOM 杀手。大多数现代系统应该有足够的磁盘空间来为大多数情况提供充足的交换文件。与其试图阻止宠物进程在过度使用内存耗尽时被杀死,不如完全避免这种情况可能更容易。[摆脱 OOM 杀手]

如果程序分配了内存,内核可以简单地将更多交换页面标记为已提交。此指示存储在内核的内存管理器中,实际磁盘空间尚未被触及。在使用该内存之前,实际上无需交换任何内容。如果从未使用过它们,则交换使用率会波动而不会影响性能。

因为进程拥有自己的地址空间或“视图”(这首先就是交换的工作方式),所以内核在管理方面有很大的余地。使用上面链接的文章中的 fork 示例,由于它更有可能拥有共享内存页面,而不是新分配大量未使用的内存,因此可以分配写时复制的内存,从而增加交换使用计数。当它实际被写入时(这可能不会发生),那么可以用任何未使用的 RAM 替换该“已提交的交换”(然后增加 RAM 使用并减少交换使用)。想象一个分配了 500MB 的进程在一台所有或几乎所有 RAM 都在使用的机器上 fork。如果交换中有 500MB 可用(并且磁盘空间很便宜,当今 TB 驱动器的 1% 有多大?:P),则无需复制任何内存(目前,可能永远不需要),但内核可以保证这些分配是“成功的”,并尽可能长时间地继续使用共享内存页面。

这样就避免了 OOM 杀手的可能性,而且在设计大多数软件时,如果假设内存分配(包括通过 fork 等方式进行的“隐式”分配)要么立即成功要么立即失败,那么设计起来就会简单得多,因为实际的认识是,如果必须交换内存,那么它可能会影响性能。这种影响几乎总是很小,但在最坏的情况下会导致交换抖动(有时仍然比直接的内核崩溃或 OOM 杀手要好)。

虽然我不知道 Linux 内存管理器的工作原理的确切细节,但这个答案是我自己对它的一般理解,也是我多年来记得读过的内容。我试图重新编辑这个答案,以便对操作系统设计有最低限度的了解(它相当复杂,而且我自己并不十分感兴趣),但它似乎有点漫无目的;如果您看到它可以如何改进,请告诉我。另一方面,这可能不是一个令人尴尬的基本问题。

相关内容