configurationvm.overcommit_memory的效果

在CentOS 5.4(Linux kernel 2.6.16.33-xenU)上运行的我的VPSnetworking服务器不规则地(像一个月一次,需要几个星期)变得没有反应,因为OOM杀手踢了进来。监视服务器显示它不通常耗尽内存,只是每隔一段时间。

我已经阅读了一些指向这个页面的博客,它讨论了使用以下sysctl设置来configuration内核以更好地pipe理overcommit:

vm.overcommit_memory = 2 vm.overcommit_ratio = 80 

我对此的理解(这可能是错误的,但我找不到一个规范的定义来澄清)是,这可以防止内核过度分配内存超过swap + 80%的内存。

不过,我也读过一些其他的消息来源,认为这些设置不是一个好主意 – 虽然这种方法的批评者似乎在说“不要做破坏你的系统的事情,而不是尝试这个混乱”因果总是众所周知的。

所以我的问题是, 这种方法的优点和缺点什么 ,在一个Apache2的网站服务器托pipe约10个低stream量的网站上下文? 在我的具体情况下,Web服务器具有512Mb的RAM,1024Mb的交换空间。 这在绝大多数时候似乎是足够的。

    overcommit_ratio设置为80可能不是正确的操作。 将该值设置为小于100的值几乎总是不正确的。

    原因是linux应用程序的分配比他们真正需要的多。 说他们分配8kb存储一对文本的string。 那好几个KB没有用在那里。 应用程序做了很多,这是overcommit的目的。

    所以,基本上在100上的overcommit,内核将不允许应用程序分配比你有更多的内存(swap + ram)。 将它设置为小于100意味着你永远不会使用你的所有内存。 如果要设置此设置,则应该将其设置为高于100,这是因为前面提到的场景很常见。

    现在,针对OOM杀手触发的问题,手动设置overcommit将不可能解决这个问题。 默认设置(启发式确定)相当智能。

    如果你想看看是否真的是这个问题的原因,那么当OOM杀手运行时,请看/proc/meminfo 。 如果您看到Committed_AS接近CommitLimit ,但free仍在显示可用内存,则可以手动调整您的scheme的overcommit。 将此值设置得太低会导致OOM杀手在您仍有足够的内存空间时开始查杀应用程序。 将它设置得太高可能会导致随机应用程序在尝试使用分配的内存时死亡,但实际上并不可用(当所有内存实际上都用完时)。

    在@dunxd提到的文档中,第9.6节“Overcommit and OOM”对于允许过量使用的危险是特别的graphics。 然而, 80看起来很有趣,所以我进行了一些testing。

    我发现overcommit_ratio会影响所有进程可用的RAM总量。 根进程似乎没有被区别于正常的用户进程。

    将比率设置为100或更less应该提供经典的语义,其中来自malloc/sbrk返回值是可靠的。 设置比率低于100可能是为caching等非进程活动预留更多RAM的一种方法。

    所以,在我的计算机上使用24 GiB的RAM,禁用了交换function,使用了9个GiB,并显示top

     Mem: 24683652k total, 9207532k used, 15476120k free, 19668k buffers Swap: 0k total, 0k used, 0k free, 241804k cached 

    以下是一些overcommit_ratio设置,以及我的ram-consumer程序可以抓取多less内存(触摸每个页面) – 在每种情况下,一旦malloc失败,程序就会彻底退出。

      50 ~680 MiB 60 ~2900 MiB 70 ~5200 MiB 100 ~12000 MiB 

    同时运行几个,甚至有一些作为根用户,并没有改变他们一起消费的总量。 有趣的是,它无法使用最后3 + GiB左右; free没有下降到这里显示的以下:

     Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers 

    实验很混乱 – 现在所有使用malloc的东西往往都会崩溃,因为很多程序员在C中检查malloc失败是很糟糕的,一些受欢迎的集合库完全忽略它,而C ++和其他各种语言甚至更差。

    我所看到的虚拟RAM的大部分早期实现都是为了处理一个非常特殊的情况,在这个情况下,一个大的进程(比如51%的可用内存)需要fork()以便exec()一些支持程序, ,小得多。 具有写入时复制语义的操作系统将允许fork() ,但是前提条件是如果分支进程实际上试图修改太多的内存页(这些内存页中的每一个都必须被实例化为独立于最初巨大的进程),最终会被杀死。 如果分配更多的内存,父进程只会处于危险之中,并且可以处理耗尽,在某些情况下只需等待一些其他进程死掉,然后继续。 subprocess通常只是通过exec()代替(通常是较小的)程序本身,然后没有附带条件。

    Linux的过度使用概念是允许fork()发生以及允许单个进程大量超额使用的极端方法。 OOM杀手造成的死亡是asynchronous发生的,甚至是负责处理内存分配的程序。 我个人讨厌整个系统范围内的过度使用,尤其是恶意软件杀手 – 它鼓励对内存pipe理采取恶魔般的照顾方式,这种方式会感染图书馆,并通过它们使用它们的每个应用程序。

    我build议将比例设置为100,并设置一个交换分区,通常最终会被巨大的进程占用 – 通常这些进程通常只使用自己部分的交换分区,因此保护绝大多数stream程免受OOM杀手的误会。 这应该保证你的networking服务器不会随机死亡,而且如果它是为了负责任地处理malloc而写的,甚至可以免于自杀(但不要在后者上下注)。

    这意味着我在/etc/sysctl.d/10-no-overcommit.conf使用这个

     vm.overcommit_memory = 2 vm.overcommit_ratio = 100