我遇到了电脑冻结问题,但我似乎无法解决。我有三台相同的电脑。它们都是定制的,配备 i7 和 64GB RAM。操作系统驱动器是 512GB NVME 驱动器。它们各自运行带有内核 v3.10 的 CentOS v7.8.2003。我正在运行一些自定义软件,该软件可以存储大量数据,对其进行处理,然后重新存储。
显示对操作系统完成的自定义配置可能相关。
自定义 fstab:
UUID=xxxxxx / ext4 noatime,nodiratime,discard 1 1
UUID=xxxxxx swap swap defaults 0 0
tmpfs /dev/shm tmpfs defaults,noatime,mode=1777 0 0
tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
LABEL=drive1 /data/drive1 auto noatime,nodiratime,discard,nofail 0 0
LABEL=drive2 /data/drive2 auto noatime,nodiratime,discard,nofail 0 0
LABEL=drive3 /data/drive3 auto noatime,nodiratime,discard,nofail 0 0
LABEL=drive4 /data/drive4 auto noatime,nodiratime,discard,nofail 0 0
LABEL=drive5 /data/drive5 auto noatime,nodiratime,discard,nofail 0 0
LABEL=drive6 /data/drive6 auto noatime,nodiratime,discard,nofail 0 0
自定义 sysctl.conf:
vm.swappiness=1
vm.vfs_cache_pressure=50
我不想过多介绍该软件的细节,但相关的是它以极快的速度接收数据。数据存储在直接连接到主板的五个 SATA SSD 上。 (并行写入 5 个是写入速度跟上数据流入的唯一方法)数据存储在大块(文件)中,稍后进行处理,然后存储到第六个 SATA SSD。我不知道某些软件如何工作的细节,但我确实知道某些进程使用大块共享内存。
问题:有时,当新的数据块传入时,PC 会冻结。这种冻结是不可恢复的,需要硬重启。它发生的时间是随机的,但总是在新数据收集开始时发生。更改软件参数和启用/禁用某些进程可能会影响冻结发生的频率。但这不允许我缩小范围,因为它似乎与特定过程无关。只是有些配置使得它更有可能发生。我确实找到了一个特定的配置,可以让我始终如一地重新创建问题,因此至少有助于测试。
我曾与编写该软件的开发人员合作过,但我们无法找到任何可能导致电脑死机的问题。我还测试了该软件的内存泄漏,但找不到任何内存泄漏。
在我看来,所有这些都指向内存问题。但是,我实际上找不到内存问题。我在命令行和 Gnome 中的系统监视器上使用了 top 和 free,但没有任何内存问题的迹象。 CPU 负载并不太高,PC 甚至没有使用 64GB RAM 的一半。如果这是一个内存问题,那么我要么丢失了某些东西,要么它发生得太快以至于监视和日志记录无法捕获它。
现在进入问题的核心:在绝望中,我的一位合伙人这样做了:
vm.overcommit_memory=2
vm.overcommit_ratio=80
这“似乎”解决了这个问题。我无法再重新创建冻结状态。如果我在执行重现问题的步骤时监视内存,我不会发现任何异常情况。没有任何进程崩溃,软件只是完成了它的设计任务。这让我觉得冻结的原因不是软件,而是操作系统的配置方式相对于 PC 的非典型使用方式。
我已阅读该文档,但对于更改 overcommit_memory 如何影响系统的其他部分或提供您何时想要更改它的任何示例,它没有帮助。我在论坛上查找了更多信息,但主要发现“除非您知道自己在做什么,否则不要碰它”。我还担心如果请求太多内存,OOM 会杀死重要进程。
有人可以告诉我您何时想要更改 overcommit_memory 设置吗?我的情况是否属于您需要改变的情况?如果是这样,我应该注意它如何影响系统的其他方面?
答案1
首先,我会检查日志是否有 OOM 的任何参考。您可能不会看到内存消耗增加,直到为时已晚,如果某个程序突然尝试一次消耗大量内存,那么可能就为时已晚了。
第二,当系统死机时,分析原因的最佳方法是启用内核崩溃转储预先,然后使用SysRq 魔术键(在这种情况下,使用ALT-SysRq-c
键盘上的组合)生成内核的核心转储,以便稍后进行分析。
关于overcommit_memory
,您可以在以下位置阅读man 5 proc
:
/proc/sys/vm/overcommit_memory
该文件包含内核虚拟内存计费模式。值为:
0: heuristic overcommit (this is the default) 1: always overcommit, never check 2: always check, never overcommit
在模式 0 下
mmap(2)
, with的调用MAP_NORESERVE
不会被检查,默认的检查很弱,导致进程“OOM-killed”的风险。在模式 2 中(自 Linux 2.6 起可用),可分配的总虚拟地址空间(中的 CommitLimit
/proc/mem‐info
)计算如下CommitLimit = (total_RAM - total_huge_TLB) * overcommit_ratio / 100 + total_swap
许多程序尝试分配内核允许它们使用的尽可能多的内存(当overcommit
默认为 0 时,这可能会非常大),然后使用它而不检查该内存是否实际上在物理上可用,这 - 正如文档所述 - 导致OOM-killer
被触发的风险。当overcommit
为2时,内核根据RAM的总大小、交换区和值来限制应用程序可以分配(映射)的内存量overcommit_ratio
,这实际上是减少触发 OOM 的机会。
当内核未能满足其mmap(2)
请求时,许多正确管理内存的应用程序不会死亡,并且只会使用内核允许它们分配的内存。
我强烈建议你阅读本文第 9.6 节 -“过度使用和 OOM”overcommit
有关更改为 2 如何影响其测试代码的行为并防止它们被 OOM 杀死的实际示例。