我正在运行一个没有交换的 Linux 工作站,并且我已经安装了earlyoom
如果内存不足,守护进程会自动终止某些进程。它earlyoom
通过监控内核MemAvailable
值来工作,如果可用内存足够低,它会终止不太重要的进程。
长期以来,这种方法一直运行良好,但突然间,我遇到了MemAvailable
与系统其他部分相比,其性能突然变得非常低的情况。例如:
$ grep -E '^(MemTotal|MemFree|MemAvailable|Buffers|Cached):' /proc/meminfo
MemTotal: 32362500 kB
MemFree: 5983300 kB
MemAvailable: 2141000 kB
Buffers: 665208 kB
Cached: 4228632 kB
请注意 MemAvailable 远低于MemFree
++ Buffers
。Cached
我可以运行什么工具来进一步调查为什么会发生这种情况?我感觉系统性能比平时差一点,我不得不停止该服务,因为除非它稳定(即,它正确地向用户模式进程描述可用内存),earlyoom
否则它的逻辑将无法工作。MemAvailable
根据https://superuser.com/a/980821/100154MemAvailable 是在不进行交换的情况下,估计有多少内存可用于启动新应用程序。由于我没有交换,这是什么意思?这是否意味着在触发 OOM Killer 之前新进程可以获得的内存量(因为这在逻辑上会遇到“交换已满”的情况)?
我曾假设MemAvailable
>=MemFree
永远为真。但这里不是。
附加信息:
在互联网上搜索后,我发现原因可能是文件系统不支持打开文件,因此无法从内存中释放这些文件。命令sudo lsof | wc -l
输出结果显示653100
,因此我绝对无法手动查看该列表。
顶部sudo slabtop
说
Active / Total Objects (% used) : 10323895 / 10898372 (94.7%)
Active / Total Slabs (% used) : 404046 / 404046 (100.0%)
Active / Total Caches (% used) : 104 / 136 (76.5%)
Active / Total Size (% used) : 6213407.66K / 6293208.07K (98.7%)
Minimum / Average / Maximum Object : 0.01K / 0.58K / 23.88K
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
4593690 4593656 99% 1.06K 153123 30 4899936K ext4_inode_cache
3833235 3828157 99% 0.19K 182535 21 730140K dentry
860224 551785 64% 0.06K 13441 64 53764K kmalloc-64
515688 510872 99% 0.66K 21487 24 343792K proc_inode_cache
168140 123577 73% 0.20K 8407 20 33628K vm_area_struct
136832 108023 78% 0.06K 2138 64 8552K pid
...
这对我来说看起来很正常。
创建粗略摘要lsof
$ sudo lsof | awk '{ print $2 }' | sort | uniq -c | sort -h | tail
6516 1118
7194 2603
7884 18727
8673 19951
25193 28026
29637 31798
38631 15482
41067 3684
46800 3626
75744 17776
指向我的 PID 17776,这是一个 VirtualBox 实例。(其他打开大量文件的进程是 Chrome、Opera 和 Thunderbird。)因此,如果我后来发现这个问题的主要原因是 VirtualBox,我不会感到太惊讶,因为这是唯一真正扰乱内核的东西。
然而,即使我关闭 virtualbox 并终止 Chrome、Opera 和 Thunderbird,问题仍然没有消失。
答案1
我可以运行什么工具来进一步调查为什么会发生这种情况?
差异可能是因为您使用了错误的计算。您链接到的答案没有突出显示这一点,但请查看链接的提交消息:
[人们]通常通过将“空闲”和“缓存”相加来实现这一点,这在十年前是可行的,但今天几乎肯定是错误的。这是错误的,因为其中
Cached
包括不能作为页面缓存释放的内存,例如共享内存段、tmpfs 和 ramfs。
其中不能作为页面缓存释放的部分Cached
(叹气)被 Shmem
算作/proc/meminfo
。
您也可以运行free
,并查看“共享”列。
这通常是由于已安装tmpfs
. 检查造成的df -h -t tmpfs
。
答案2
正如您在所引用的文章中所看到的,围绕 MemAvailable 的整套计算都是围绕计算有多少内存可供使用而不会导致任何交换而构建的。您可以在实际补丁实现了 MemAvailable 数字,即 MemAvailable = MemFree - LowWaterMark + (PageCache - min(PageCache / 2, LowWaterMark))
此公式指出了系统的 MemAvailable 较低的概率,因为您的低水位标记(系统认为需要作为工作空间的可用内存量)可能非常高。这在无交换环境中是有意义的,因为系统更担心内存耗尽。您可以查看当前的低水位标记是多少:
$ cat /proc/sys/vm/min_free_kbytes
我怀疑就你的情况来说,这个数字相当高。
Linux 内存管理中的几乎所有启发式方法都假设您将使用一些交换空间进行操作。
答案3
对于现代 Linux 内核,该Cached
值包含磁盘缓存和所有共享内存。由于只能删除磁盘缓存,因此不能将其视为可用内存。我在邮件列表中询问了这个问题linux-mm
,普遍的共识是,Cached
由于向后兼容,计算方式不能改变,尽管当前计算对于标签“缓存”有点问题。传统的缓存值应(Cached - Shmem)
与现代内核一样计算。
如今,您应该相信MemAvailable
在实践中描述实际可用的内存。如果您想要更详细的细分,您可能应该从中获取数据/proc/meminfo
并计算Free
++ 。该计算不同于释放非活动文件缓存需要 IO。还要注意,如果内核实际上要释放所有,Inactive(file)
那么整体吞吐量也可能会受到很大影响。是一种启发式方法,它试图猜测可以在当前工作负载之上使用的可用 RAM,而不会严重损害当前工作负载的吞吐量。这显然不同于不会导致系统崩溃的理论最大可用内存。KReclaimable
MemAvailable
KReclaimable
MemAvailable