@dunxd提到的文档中的第9.6节“过量使用和OOM”特别是关于允许过量使用的危险的图形。但是,该80
外观对我也很有趣,因此我进行了一些测试。
我发现这overcommit_ratio
会影响所有进程可用的总RAM。根进程似乎与普通用户进程没有什么不同。
将比率设置为100
或小于应该提供经典的语义,其中返回值malloc/sbrk
是可靠的。将其比率设置为低于100
可能为非进程活动(例如缓存等)保留更多RAM的一种方式。
因此,在我的具有24 GiB RAM的计算机上,禁用了交换功能,正在使用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程序可以获取多少RAM(触摸每页)-在每种情况下,一旦malloc
失败,程序都会干净退出。
50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
一次运行多个,即使以root用户身份运行一个,也不会改变他们一起消耗的总金额。有趣的是,它无法消耗最近的3+ GiB左右。在free
没降远低于此处显示的:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
实验是混乱的-由于所有程序员都非常担心在C中检查malloc失败,因此在使用所有RAM时立即使用malloc的任何事情都会崩溃,一些流行的集合库完全忽略了它,甚至C ++和其他各种语言也是如此。更差。
我看到的虚构RAM的大多数早期实现都是处理一个非常特殊的情况,在这种情况下,fork()
为了exec()
支持某个程序,通常需要一个大得多的程序,例如一个可用内存的51%以上。具有写时复制语义的OS允许使用fork()
,但附带条件是,如果分叉的进程实际上试图修改太多的内存页面(然后必须将每个内存页面实例化为独立于初始大型进程的新页面)最终会被杀死。父进程只有在分配更多内存时才处于危险之中,并且可以处理耗尽,在某些情况下,只需稍等一些其他进程终止,然后继续运行即可。子进程通常通过以下方式(通常是较小的)程序代替自身:exec()
然后摆脱了附带条件
Linux的过量使用概念是一种极端的方法,它既可以使之fork()
同时发生,也可以使单个进程得以大规模整合。由OOM杀手引起的死亡异步发生,即使是确实负责地处理内存分配的程序也是如此。我个人讨厌整个系统的过度使用,尤其是oom-killer-它在内存管理中采用了一种“恶魔般贴心”的方法,这种方法会感染库以及使用它们的每个应用程序。
我建议将比率设置为100,并且还要有一个交换分区,它通常只会最终被大型进程使用-这些进程通常只使用自身一部分的很小一部分,从而塞入交换中,因此保护大多数进程免受OOM杀手功能的影响。这应该可以保护您的Web服务器免遭随机死亡的威胁,并且如果它被编写为malloc
负责任地处理,甚至可以防止其自杀(但不要押注后者)。
那意味着我在用这个 /etc/sysctl.d/10-no-overcommit.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 100