La sezione 9.6 "Overcommit e OOM" nel documento che @dunxd menziona è particolarmente grafica sui pericoli di consentire l'overcommit. Tuttavia, 80
mi è sembrato interessante anche per me, quindi ho condotto alcuni test.
Quello che ho scoperto è che overcommit_ratio
influenza la RAM totale disponibile per TUTTI i processi. I processi di root non sembrano essere trattati in modo diverso dai normali processi dell'utente.
L'impostazione del rapporto su 100
o meno dovrebbe fornire la semantica classica da cui i valori di ritorno malloc/sbrk
sono affidabili. Impostare rapporti inferiori a quelli che 100
potrebbero essere un modo per riservare più RAM per attività non di processo come la memorizzazione nella cache e così via.
Quindi, sul mio computer con 24 GiB di RAM, con swap disabilitato, 9 GiB in uso, con top
visualizzazione
Mem: 24683652k total, 9207532k used, 15476120k free, 19668k buffers
Swap: 0k total, 0k used, 0k free, 241804k cached
Ecco alcune overcommit_ratio
impostazioni e la quantità di RAM che il mio programma ram-consumer potrebbe raccogliere (toccando ogni pagina) - in ogni caso il programma è uscito in modo pulito una volta malloc
fallito.
50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
Eseguirne diversi contemporaneamente, anche con alcuni come utente root, non ha modificato la quantità totale consumata insieme. È interessante che non sia stato in grado di consumare gli ultimi 3+ GiB o giù di lì; il free
non è sceso molto al di sotto di quanto mostrato qui:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
Gli esperimenti sono stati disordinati: tutto ciò che utilizza malloc al momento, tutta la RAM in uso tende a bloccarsi, dal momento che molti programmatori sono terribili nel controllare gli errori di malloc in C, alcune librerie di raccolte popolari lo ignorano del tutto, e C ++ e varie altre lingue sono persino peggio.
La maggior parte delle prime implementazioni della RAM immaginaria che ho visto sono state per gestire un caso molto specifico, in cui un singolo grande processo - diciamo il 51% + di memoria disponibile - era necessario fork()
per exec()
un programma di supporto, di solito molto, molto più piccolo. I sistemi operativi con semantica copy-on-write consentirebbero fork()
, ma a condizione che se il processo biforcato tentasse effettivamente di modificare troppe pagine di memoria (ognuna delle quali dovrebbe quindi essere istanziata come una nuova pagina indipendente dall'enorme processo iniziale) finirebbe per essere ucciso. Il processo genitore era in pericolo solo se allocava più memoria e riusciva a esaurirsi, in alcuni casi semplicemente aspettando che un altro processo morisse e poi continuava. Il processo figlio di solito si è appena sostituito con un programma (generalmente più piccolo) tramiteexec()
ed era quindi libero dalla condizione.
Il concetto di overcommit di Linux è un approccio estremo per consentire sia il fork()
verificarsi sia per consentire ai singoli processi di sovrallocare in modo massiccio. Morti OOM-killer-causata avvengono in modo asincrono, anche per i programmi che fanno allocazione di memoria maniglia in modo responsabile. Personalmente odio il sovraccarico a livello di sistema in generale e l'oom-killer in particolare - promuove un approccio diabolico alla cura della memoria che infetta le librerie e attraverso di esse ogni app che le utilizza.
Suggerirei di impostare il rapporto su 100 e di avere anche una partizione di swap che generalmente finirebbe solo per essere utilizzata da enormi processi - che spesso usano solo una piccola parte della parte di se stessi che viene inserita nello swap, e quindi proteggere la stragrande maggioranza dei processi dalle disfunzioni del killer OOM. Ciò dovrebbe proteggere il tuo server Web dalla morte casuale e, se è stato scritto per gestire in modo malloc
responsabile, anche sicuro dall'uccidere se stesso (ma non scommettere su quest'ultimo).
Ciò significa che sto usando questo in /etc/sysctl.d/10-no-overcommit.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 100