GNU/Linux >> Znalost Linux >  >> Linux

Účinky konfigurace vm.overcommit_memory

Řešení 1:

Nastavení overcommit_ratio na 80 pravděpodobně není správná akce. Nastavení hodnoty na cokoliv menšího než 100 je téměř vždy nesprávné.

Důvodem je to, že linuxové aplikace alokují více, než skutečně potřebují. Řekněme, že alokují 8 kb pro uložení několika znakového řetězce textu. To je několik KB nevyužitých. Aplikace to dělají hodně a k tomu je určen overcommit.

Takže v podstatě s overcommitem na 100 jádro nedovolí aplikacím alokovat více paměti, než máte (swap + ram). Nastavení na méně než 100 znamená, že nikdy nevyužijete celou svou paměť. Pokud se chystáte nastavit toto nastavení, měli byste ho nastavit na vyšší hodnotu než 100 kvůli výše zmíněnému scénáři, což je docela běžné.

Nyní, pokud jde o váš problém se spouštěním OOM zabijáka, ruční nastavení overcommit to pravděpodobně nevyřeší. Výchozí nastavení (heuristické určení) je poměrně inteligentní.

Chcete-li zjistit, zda je toto skutečně příčinou problému, podívejte se na /proc/meminfo když OOM zabiják běží. Pokud vidíte, že Committed_AS se blíží CommitLimit , ale free stále zobrazuje dostupnou volnou paměť, pak ano, můžete ručně upravit překročení pro váš scénář. Nastavení této hodnoty příliš nízko způsobí, že OOM zabiják začne zabíjet aplikace, když máte stále dostatek volné paměti. Nastavení příliš vysoké může způsobit, že náhodné aplikace zemřou, když se pokusí využít paměť, která jim byla přidělena, ale ve skutečnosti není dostupná (když se všechna paměť skutečně spotřebuje).

Řešení 2:

Oddíl 9.6 „Overcommit and OOM“ v dokumentu, který @dunxd zmiňuje, je obzvláště názorný na nebezpečí povolení overcommit. Nicméně malloc/sbrk také mi to připadalo zajímavé, tak jsem provedl několik testů.

Zjistil jsem, že overcommit_ratio ovlivňuje celkovou RAM dostupnou pro VŠECHNY procesy. Zdá se, že s kořenovými procesy se nezachází jinak než s běžnými uživatelskými procesy.

Nastavení poměru na 100 nebo méně by měly poskytovat klasickou sémantiku, kde vrací hodnoty z malloc/sbrk jsou spolehlivé. Nastavení poměrů nižší než 100 může být způsob, jak vyhradit více paměti RAM pro neprocesní činnosti, jako je ukládání do mezipaměti a tak dále.

Takže na mém počítači s 24 GiB RAM, se zakázaným swapem, 9 GiB v použití, s top zobrazení

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

Zde jsou některé overcommit_ratio nastavení a kolik RAM mohl můj spotřebitelský program ram uchopit (dotykem na každou stránku) - v každém případě se program ukončil čistě jednou malloc selhalo.

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

Spuštění několika najednou, dokonce i s některými jako uživatel root, nezměnilo celkové množství, které společně spotřebovali. Je zajímavé, že nebyl schopen spotřebovat posledních 3+ GiB nebo tak; free nekleslo moc pod to, co je zde zobrazeno:

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

Experimenty byly chaotické – vše, co v tuto chvíli používá malloc, má tendenci se zhroutit, protože mnoho programátorů je hrozných při kontrole chyb malloc v C, některé oblíbené knihovny sbírek to zcela ignorují a C++ a různé další jazyky jsou dokonce horší.

Většina raných implementací imaginární paměti RAM, které jsem viděl, řešila velmi specifický případ, kdy jeden velký proces – řekněme 51 %+ dostupné paměti – potřeboval fork() za účelem exec() nějaký podpůrný program, obvykle mnohem, mnohem menší. Operační systémy se sémantikou kopírování při zápisu by umožnily fork() , ale s výhradou, že pokud by se rozvětvený proces skutečně pokusil upravit příliš mnoho paměťových stránek (každá z nich by pak musela být vytvořena jako nová stránka nezávislá na počátečním obrovském procesu), skončilo by to smrtí. Rodičovský proces byl v nebezpečí pouze v případě, že by alokoval více paměti, a mohl zvládnout vyčerpání, v některých případech jen tak, že chvíli počkal, než nějaký jiný proces zemře, a pak pokračoval. Podřízený proces se obvykle jen nahradil (obvykle menším) programem přes exec() a byl poté osvobozen od výhrady.

Koncepce linuxového overcommit je extrémním přístupem k umožnění obou fork() aby se vyskytly a zároveň umožnily masivní přetížení jednotlivých procesů. K úmrtím způsobeným vrahem OOM dochází asynchronně, a to i u programů, které dělají zodpovědně zacházet s alokací paměti. Osobně nesnáším celosystémové overcommit obecně a oom-killer konkrétně – podporuje přístup ke správě paměti, který infikuje knihovny a prostřednictvím nich každou aplikaci, která je používá.

Navrhoval bych nastavit poměr na 100 a mít také swapovací oddíl, který by obecně nakonec využívaly pouze obrovské procesy – které často využívají jen nepatrný zlomek své části, která se nacpe do swapu, a tedy chránit drtivou většinu procesů před chybnou funkcí zabijáka OOM. To by mělo ochránit váš webový server před náhodnou smrtí a pokud byl napsán tak, aby zpracovával malloc zodpovědně, dokonce v bezpečí před sebevraždou (ale nesázejte na to druhé).

To znamená, že to používám v /etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100

Linux
  1. Analýza případů pro a proti nastavení odkládacího prostoru na cloudových instancích

  2. Jak vymazat mezipaměť v Linuxu

  3. Linux – skutečné využití paměti?

  1. Grep:Vyčerpaná paměť?

  2. Nastavení názvu hostitele v Docker Compose

  3. Limit paměti PHP

  1. Využití paměti Linuxu

  2. Jenkins aktivní (opuštěno)

  3. Linuxová neaktivní paměť