“缓存”内存实际上是免费的吗?

“缓存”内存实际上是免费的吗?

运行时cat /proc/meminfo,您会在顶部获得以下 3 个值:

MemTotal:        6291456 kB
MemFree:         4038976 kB
Cached:          1477948 kB

据我所知,“Cached”值是Linux系统创建的磁盘缓存,如果任何应用程序需要更多RAM,它将立即释放,因此Linux永远不会耗尽内存,直到MemFree和Cached都为零。

不幸的是,/proc/meminfo 没有报告“MemAvailable”,可能是因为它在虚拟服务器中运行。 (内核版本为4.4)

因此,出于所有实际目的,可供应用程序使用的 RAM 是 MemFree + Cached。

这种观点正确吗?

答案1

在许多现实案例中,这种观点可能非常具有误导性。

内核现在提供了现场可用内存的估计MemAvailable。该值与 显着不同MemFree + Cached

/proc/meminfo:提供估计的可用内存[内核更改说明,2014 年]

许多负载平衡和工作负载放置程序都会检查 /proc/meminfo 以估计有多少可用内存。他们通常通过将“免费”和“缓存”相加来做到这一点,这在十年前还不错,但今天几乎肯定是错误的。

这是错误的,因为 Cached 包含不可作为页面缓存释放的内存,例如共享内存段、tmpfs 和 ramfs,并且它不包含可回收的平板内存,在大多数空闲的系统上,这些内存可能会占用大部分系统内存很多文件。

目前,可以根据 MemFree、Active(file)、Inactive(file) 和 SReclaimable 以及 / 的“低”水印来估计可用于新工作负载的内存量,而无需将系统推入交换区。过程/区域信息。然而,这种情况将来可能会改变,并且用户空间确实不应该期望了解内核内部结构来估计可用内存量。在 /proc/meminfo 中提供这样的估计会更方便。如果将来事情发生变化,我们只需改变一处即可。
...

Documentation/filesystems/proc.txt:
...
MemAvailable:估计有多少内存可用于启动新应用程序,无需交换。根据 MemFree、SReclaimable、文件 LRU 列表的大小以及每个区域中的低水位线计算得出。该估计考虑到系统需要一些页面缓存才能正常运行,并且由于项目正在使用,并非所有可回收的slab都是可回收的。这些因素的影响因系统而异。

1.MeM可用详情

正如上面所说,tmpfs 和其他Shmem内存无法释放,只能移至交换区。 由于包含了可交换内存,Cached因此可能会产生很大的误导。如果 tmpfs 中有太多文件,它可能会占用大量内存:-)。 还可以包括一些/proc/meminfoShmemShmem图形内存分配,这可能非常大。

MemAvailable故意不包括可交换内存。交换太多可能会导致长时间的延迟。您甚至可能选择在没有交换空间的情况下运行,或者只允许相对有限的数量。

我必须仔细检查如何MemAvailable运作。乍一看,代码中似乎没有提到这个区别。

/*
 * Not all the page cache can be freed, otherwise the system will
 * start swapping. Assume at least half of the page cache, or the
 * low watermark worth of cache, needs to stay.
 */
pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
pagecache -= min(pagecache / 2, wmark_low);
available += pagecache;

但是,我发现它正确地视为Shmem“已用”内存。我在 tmpfs 中创建了几个 1GB 的文件。每增加1GB就Shmem减少MemAvailable1GB。因此“文件 LRU 列表”的大小不包括共享内存或任何其他可交换内存。 (我注意到这些相同的页数也被使用在计算“脏限制”的代码中)。

MemAvailable计算还假设您希望保留至少足够的文件缓存以等于内核的“低水位线”。或当前缓存的一半 - 以较小者为准。 (它也对可回收平板做出相同的假设)。内核的“低水位线”可以调整,但通常是大约系统 RAM 的 2%。因此,如果您只想粗略估计,可以忽略这部分:-)。

当您在页面缓存中映射大约 100MB 的程序代码来运行时firefox,您通常希望将这 100MB 保留在 RAM 中:-)。否则,最好的情况是您会遭受延迟,最坏的情况是系统将花费所有时间殴打不同应用程序之间。MemAvailable为此允许一小部分 RAM 也是如此。它可能允许的不够,或者可能过于慷慨。 “这些因素的影响因系统而异”。

对于许多 PC 工作负载,“大量文件”这一点可能并不相关。即便如此,我的笔记本电脑上目前有 500MB 可回收平板内存(8GB RAM)。这是由于ext4_inode_cache(超过 300K 对象)。发生这种情况是因为我最近必须扫描整个文件系统,以查找正在使用我的磁盘空间的内容:-)。我使用了命令df -x / | sort -n,但是例如 Gnome Disk Use Analyzer 会做同样的事情。

2. [编辑] 对照组的记忆

所谓的“Linux 容器”是根据喜好由namespaces、和各种其他功能构建的:-)。cgroups它们可能提供一个足够令人信服的环境来运行几乎像完整 Linux 系统的东西。托管服务可以构建这样的容器并将它们作为“虚拟服务器”出售:-)。

托管服务器还可以使用主线 Linux 中没有的功能来构建“虚拟服务器”。 开放VZ容器比主线 cgroup 早两年,并且可以使用“beancounters”来限制内存。因此,如果您只阅读文档或询问有关主线 Linux 内核的问题,您就无法准确理解这些内存限制是如何工作的。 cat /proc/user_beancounters显示当前的使用情况和限制。 vzubc以稍微更友好的格式呈现它。这beancounters 的主页记录行名称。

控制组包括对其内部进程设置内存限制的能力。如果您在这样的 cgroup 内运行应用程序,则并非所有系统内存都可供应用程序使用:-)。那么,在这种情况下我们如何才能看到可用内存呢?

其界面在很多方面有所不同,具体取决于您是否使用cgroup-v1或者cgroup-v2

我的笔记本电脑安装使用 cgroup-v1。我可以跑cat /sys/fs/cgroup/memory/memory.stat。该文件显示各种字段,包括total_rss, total_cache, total_shmem. shmem(包括 tmpfs)计入内存限制。我想你可以将total_rss其视为 的逆等价物MemFree。还有文件memory.kmem.usage_in_bytes,代表内核内存,包括板。 (我假设memory.kmem.还包括memory.kmem.tcp.任何未来的扩展,尽管没有明确记录)。没有单独的计数器来查看可回收的平板内存。 cgroup-v1 的文档说达到内存限制确实不是触发回收任何slab内存。 (该文档还有一个免责声明,指出它“已经过时了”,您应该检查当前的源代码)。

cgroup-v2 不同。我认为根(顶级)cgroup 不支持内存核算。 cgroup-v2 仍然有一个memory.stat文件。所有字段都会对子 cgroup 进行求和,因此您无需查找total_...字段。有一个file字段,表示cache做了同样的事情。令人烦恼的是,我没有看到像rssinside这样的整体字段memory.stat;我想你必须将各个字段相加。可回收和不可回收的slab内存有单独的统计数据;我认为 v2 cgroup 的设计目的是在内存开始不足时回收平板。

Linux cgroup 不会自动虚拟化/proc/meminfo(或 中的任何其他文件/proc),因此会显示整个计算机的值。这会让 VPS 客户感到困惑。但是可以使用命名空间来替换/proc/meminfo文件由特定容器软件伪造。假值的有用程度取决于特定软件的功能。

systemd认为 cgroup-v1 不能安全地委托给容器等。我查看了systemd-nspawncgroup-v1 系统上的容器内部。我可以看到它被放置在里面的cgroup,以及其中的内存占用。另一方面,包含的内容systemd不会设置通常的每服务 cgroup 来进行资源核算。如果此 cgroup 内未启用内存核算,我认为容器将无法启用它。

我假设如果您位于 cgroup-v2 容器内,它将看起来与真实 cgroup-v2 系统的根不同,并且您将能够看到其顶级 cgroup 的内存占用。或者,如果您看到的 cgroup 没有启用内存统计,希望您能够被委派权限,这样您就可以启用内存统计systemd(或同等学历)。

答案2

对于现代 Linux 内核和/proc/meminfo,该Cached值包括所有Shmem这些也包括所有tmpfs使用情况,因此如果需要的话,程序使用它绝对不是事实上免费的。根据我的经验,与Cached - Shmem实际可释放内存非常匹配。请注意,如果不终止进程,则无法释放任何一个Shmem,但如果内存不足,则可以交换它们。

我建议检查这些值(我的示例输出):

$ grep -E "^MemTotal|^Cached|^Committed_AS|^Shmem:|^MemAvailable|^MemFree" /proc/meminfo 
MemTotal:       32570668 kB
MemFree:         8245572 kB
MemAvailable:    7817776 kB
Cached:         11553648 kB
Shmem:          10604700 kB
Committed_AS:   36945628 kB

另请注意,myMemAvailable小于,MemFree因为一些内存估计是碎片化的,无法直接以充分的性能使用。

您的实际可用空间的另一个估计Cached可以这样找到:

$ sudo slabtop -sc -o | head | grep "Total Size"
 Active / Total Size (% used)       : 548703.26K / 672516.95K (81.6%)

请注意,在我的例子中,大约 550 MB 正在使用中,如果释放,将导致系统性能下降。

长话短说:不要看这些名称FreeCached因为它们的真正目的具有误导性,只需看看MemAvailable您可以在需要时花费更多的 RAM 量。

相关内容