多年来,OOM 杀手我的操作系统无法正常工作并导致系统冻结。
当内存使用率非常高时,整个系统往往会“冻结”(实际上:变成极其慢)对于小时甚至天,而不是杀死进程来释放内存。
我记录的最长时间为 7 天,然后我就辞职进行重置。
当即将达到 OOM 时,等待在变得无法测量之前非常非常高(~ 70%)。
该工具:iotop
显示每个程序都以非常高的吞吐量(每数十MB/秒)从我的硬盘读取。
那些程序正在读什么?
- 目录层次结构?
- 可执行代码本身?
我现在不太清楚。
[已编辑] 在我写此消息时(2017 年),我正在使用最新的 ArchLinux (4.9.27-1-lts),但几年前就已经遇到过这个问题。
我在不同的 Linux 发行版和不同的硬件配置中都遇到过同样的问题。
目前(2019),我使用的是最新的 Debian 9.6 (4.9.0) 我有16 GB物理 RAM,安装了我的操作系统的 SSD,而不是任何交换分割。
由于我拥有的内存量很大,我不想启用交换分区,因为它只会延迟问题的出现。
此外,SSD 交换过于频繁可能会缩短磁盘的使用寿命。
顺便说一句,我已经尝试过使用和不使用交换分区,事实证明它只能延迟问题的出现,而不能解决问题。
对我来说,这个问题是由于 Linux 删除了重要数据而引起的。缓存,这会导致系统冻结,因为它每次都必须从硬盘驱动器读取所有内容。
我什至想知道Linux是否不会删除正在运行的程序的可执行代码页,这可以解释为什么通常不读取大量数据的程序在这种情况下会表现出这种行为。
我尝试了几种方法希望能解决这个问题。
一种是设置/proc/sys/vm/min_free_kbytes
为1000000
(1 GB)。
因为这1GB应该保持空闲,我认为这块内存会被Linux保留来缓存重要数据。
但它没有奏效。
另外,我认为补充一点很有用,即使理论上听起来不错,通过定义 to 将虚拟内存的大小限制为物理内存的大小,在我的情况/proc/sys/vm/overcommit_memory
下2
在技术上不太可能,因为应用程序的类型由于某些原因,我使用的虚拟内存需要比其有效使用更多的虚拟内存。
根据该文件/proc/meminfo
,该Commited_AS
值通常高于我系统上物理内存的两倍(16 GB,已提交_AS通常 > 32 GB)。
/proc/sys/vm/overcommit_memory
我在默认值: 的情况下遇到过这个问题0
,并且有一段时间我将其定义为: 1
,因为我更喜欢程序被OOM 杀手而不是因为它们不检查malloc
分配被拒绝时的返回值而表现错误。
当我在网上谈论这个问题时IRC,我遇到过其他 Linux 用户也遇到过同样的问题,所以我猜很多用户都担心这个问题。
对我来说这是不可接受的,因为即使 Windows 也能更好地处理高内存使用情况。
如果您需要更多信息,有建议,请告诉我。
文档:
https://en.wikipedia.org/wiki/Thrashing_%28computer_science%29
https://en.wikipedia.org/wiki/Memory_overcommitment
https://www.kernel.org/doc/Documentation/sysctl/vm.txt
https://www.kernel.org/doc/Documentation/vm/overcommit-accounting
https://lwn.net/Articles/317814/
他们谈论它:
为什么 linux 内存不足 (OOM) 杀手不会自动运行,而是作用于 sysrq-key?
为什么 OOM-killer 有时无法杀死资源占用者?
预加载 OOM Killer
是否有可能在强制交换时触发 OOM-killer?
如何避免接近 OOM 的高延迟情况?
https://lwn.net/Articles/104179/
https://bbs.archlinux.org/viewtopic.php?id=233843
答案1
我找到了两个解释(同一件事)来解释为什么kswapd0 会持续读取磁盘发生在 OOM-killer 杀死有问题的进程之前:
- 查看答案和评论这个askubuntu SE答案
- 请参阅答案和大卫施瓦茨的评论这个答案在unix SE上
我将在这里引用 1. 的评论,这确实让我大开眼界,为什么我在一切都正常的情况下却不断地读取磁盘冷冻的:
例如,考虑一下交换空间为零且系统几乎耗尽 RAM 的情况。内核将从例如 Firefox 获取内存(它可以这样做,因为 Firefox 正在运行已从磁盘加载的可执行代码 - 如果需要,可以再次从磁盘加载代码)。如果 Firefox 在 N 秒后需要再次访问该 RAM,CPU 会生成“硬故障”,迫使 Linux 释放一些 RAM(例如,从另一个进程中获取一些 RAM),从磁盘加载丢失的数据,然后允许 Firefox 继续运行通常。这与普通交换非常相似,kswapd0 就是这样做的。 – Mikko Rantalainen 2 月 15 日 13:08
如果有人有办法如何禁用此行为(也许使用什么选项重新编译内核?),请尽快告知我!非常感谢,谢谢!
更新:到目前为止,我发现的唯一方法是通过修补内核,它对我来说在禁用交换的情况下有效(即。CONFIG_SWAP is not set
),但对其他启用交换的人不起作用似乎;看里面的补丁这问题。
答案2
EarlyOOM 实用程序是此问题的实用解决方案。 https://fedoraproject.org/wiki/Changes/EnableEarlyoom
该实用程序将监视内存使用情况,并在总内存使用量超过可配置阈值(例如 95%)之前终止大量消耗者。
它是为 Arch Linux 打包的earlyoom
,它附带了一个 systemd 服务,所以你可以快速安装它:
pacman -S earlyoom
systemctl enable earlyoom
systemctl start earlyoom
我已经使用它几个星期了,这是一个日夜的区别:尽管使用一些消耗内存的应用程序(Java、Electron 和浏览器)将系统推向了极限,但系统不再冻结。我还没有亲眼目睹它杀死了错误的进程,我认为这在理论上可能会发生。也许这在理论上是一个无法解决的问题,因为网上已经写了很多关于它的解释,但在实践中,简单的启发式方法非常有效。
答案3
memory.min
内存控制器中的参数应该cgroups-v2
有所帮助。
也就是说,让我引用:
硬内存保护。如果 cgroup 的内存使用量在其有效最小边界内,则该 cgroup 的内存在任何情况下都不会被回收。如果没有可用的未受保护的可回收内存,则会调用 OOM 杀手。
来源 :https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html