vm.overcommit_memory 如何工作?

Mik*_*kov 61 memory kernel sysctl

当我使用默认设置时:

vm.overcommit_memory = 0
vm.overcommit_ratio = 50
Run Code Online (Sandbox Code Playgroud)

我可以从/proc/meminfo文件中读取这些值:

CommitLimit:     2609604 kB
Committed_AS:    1579976 kB
Run Code Online (Sandbox Code Playgroud)

但是,当我vm.overcommit_memory从更改0为 时2,我无法启动更改前可以启动的同一组应用程序,尤其是 amarok。我不得不更改vm.overcommit_ratio300,因此可以增加限制。现在,当我启动 amarok 时,/proc/meminfo显示以下内容:

CommitLimit:     5171884 kB
Committed_AS:    3929668 kB
Run Code Online (Sandbox Code Playgroud)

这台机器只有 1GiB 的内存,但是 amarokvm.overcommit_memory设置为 0时没有问题。但是在设置为 的情况下2,amarok 需要分配超过 2GiB 的内存。这是正常行为吗?如果是这样,谁能解释为什么,例如,firefox(比 amarok 消耗的内存多 4-6 倍)在更改前后以相同的方式工作?

Kyl*_*ndt 86

您可以在man 5 proc(或在 kernel.org ) 中找到文档:

/proc/sys/vm/overcommit_memory
       This file contains the kernel virtual memory accounting mode.
       Values are:

              0: heuristic overcommit (this is the default)
              1: always overcommit, never check
              2: always check, never overcommit

       In mode 0, calls of mmap(2) with MAP_NORESERVE are not
       checked, and the default check is very weak, leading to the
       risk of getting a process "OOM-killed".

       In mode 2 (available since Linux 2.6), the total virtual
       address space that can be allocated (CommitLimit in /proc/mem?
       info) is calculated as

           CommitLimit = (total_RAM - total_huge_TLB) *
                         overcommit_ratio / 100 + total_swap
Run Code Online (Sandbox Code Playgroud)

简单的答案是,将 overcommit 设置为 1,将设置阶段,以便当程序调用诸如malloc()分配一块内存 ( man 3 malloc) 之类的东西时,无论系统是否知道它不会拥有所有正在使用的内存要求。

要理解的基本概念是虚拟内存的概念。程序看到的虚拟地址空间可能会或可能不会映射到实际物理内存。通过禁用过度使用检查,您可以告诉操作系统假设始终有足够的物理内存来备份虚拟空间。

例子

要强调为什么有时这很重要,请查看有关为什么应将其设置为 1的Redis 指南vm.overcommit_memory

  • 但是在这两种情况下,`Committed_AS` 的值不应该相同吗? (2认同)
  • @MikhailMorfikov:是的,实际上我认为 0 最有意义。在我的环境中,我唯一一次为 Redis 启用 1,它执行 * 期望 * 由于 fork() 而需要更多内存的情况。孩子几乎会使用所有相同的内存页面,但是 Linux 不知道为了安全,它必须假设将使用 2x 内存(如果您想了解更多信息:http://redis.io/topics/常问问题) (2认同)

d4n*_*yll 11

这是一个老问题,有一个公认的答案,但我认为还有更多要补充的。

首先,当 时vm.overcommit_memory = 0,该vm.overcommit_ratio值无关紧要。内核将使用启发式算法来过量使用内存,以便为您的amarok进程分配比可用内存更多的内存。

当您设置vm.overcommit_memory为 时2,该vm.overcommit_ratio值变得相关。默认情况下,此值设置为50,这意味着系统最多只能分配 50% 的 RAM(加上交换区)。这解释了为什么您无法启动正常的程序vm.overcommit_memory = 0- 因为可分配内存少于 500MB(假设没有交换)。

当您将其设置为 时300,您将允许系统分配多达 300% 的 RAM(加上交换区,如果有的话),这就是为什么CommitLimitin的值/proc/meminfo如此之高。

虽然vm.overcommit_memory = 2通常用于防止过度使用,但在这里,您使用它来限制可以过度使用的数量。将它设置为300很危险,因为您的系统没有5171884 kB内存,因此,根据您有多少交换空间,系统将使用交换(这很慢),或者将完全耗尽内存。

至于为什么amarok在什么时候使用更多内存vm.overcommit_memory = 2- 这可能是因为使用更多内存amarok效果最好,但使用更少内存也很好。所以程序的逻辑最初可能会尝试分配 2GB 的内存,但如果失败,则尝试分配 1GB。