我什么时候应该改变 overcommit_memory 以及这样做时我应该考虑什么?

我什么时候应该改变 overcommit_memory 以及这样做时我应该考虑什么?

我遇到了电脑冻结问题,但我似乎无法解决。我有三台相同的电脑。它们都是定制的,配备 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 杀死的实际示例。

相关内容