In Abschnitt 9.6, „Overcommit und OOM“ des Dokuments, das von @dunxd erwähnt wird, werden die Gefahren einer Überbeanspruchung besonders deutlich. Das 80
sah aber auch für mich interessant aus, deshalb habe ich ein paar Tests durchgeführt.
Was ich festgestellt habe, ist, dass sich dies overcommit_ratio
auf den gesamten für ALLE Prozesse verfügbaren RAM auswirkt. Root-Prozesse scheinen nicht anders behandelt zu werden als normale Benutzerprozesse.
Das Setzen des Verhältnisses auf 100
oder weniger sollte die klassische Semantik liefern, bei der Rückgabewerte malloc/sbrk
zuverlässig sind. Durch Festlegen eines niedrigeren Verhältnisses können Sie 100
mehr RAM für nicht prozessbezogene Aktivitäten wie Caching usw. reservieren.
Also, auf meinem Computer mit 24 GB RAM, mit deaktiviertem Swap, 9 GB im Einsatz, mit top
Anzeigen
Mem: 24683652k total, 9207532k used, 15476120k free, 19668k buffers
Swap: 0k total, 0k used, 0k free, 241804k cached
Hier sind einige overcommit_ratio
Einstellungen und wie viel RAM mein RAM-Consumer-Programm abrufen könnte (Berühren jeder Seite) - in jedem Fall wurde das Programm nach einem Fehler sauber beendet malloc
.
50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
Wenn mehrere gleichzeitig ausgeführt wurden, selbst wenn einige als Root-Benutzer fungierten, änderte sich nicht die Gesamtmenge, die sie zusammen verbrauchten. Es ist interessant, dass es nicht in der Lage war, die letzten 3+ GiB oder so zu konsumieren. Das free
hat nicht viel unterschritten, was hier gezeigt wird:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
Die Experimente waren chaotisch - alles, was im Moment malloc verwendet, neigt zum Absturz, da viele Programmierer schreckliche Angst haben, in C nach malloc-Fehlern zu suchen, einige beliebte Sammlungsbibliotheken es vollständig ignorieren und C ++ und verschiedene andere Sprachen sogar schlechter.
Die meisten der frühen Implementierungen von imaginärem RAM betrafen einen sehr speziellen Fall, in dem ein einzelner großer Prozess - etwa 51% des verfügbaren Speichers - erforderlich war, fork()
um exec()
ein Support-Programm zu erstellen, normalerweise ein viel, viel kleineres. Betriebssysteme mit Copy-on-Write-Semantik würden das zulassen fork()
, jedoch mit der Maßgabe, dass, wenn der Fork-Prozess tatsächlich versucht, zu viele Speicherseiten zu ändern (von denen jede unabhängig vom anfänglichen riesigen Prozess als neue Seite instanziiert werden müsste). es würde am Ende getötet werden. Der übergeordnete Prozess war nur dann in Gefahr, wenn mehr Speicher zugewiesen wurde, und konnte das Auslaufen in einigen Fällen bewältigen, indem er nur ein bisschen darauf wartete, dass ein anderer Prozess ausfiel, und dann fortfuhr. Der untergeordnete Prozess hat sich normalerweise nur durch ein (normalerweise kleineres) Programm über ersetztexec()
und war dann frei von der Maßgabe.
Das Overcommit-Konzept von Linux ist ein extremer Ansatz, um sowohl das fork()
Auftreten als auch die Überlagerung einzelner Prozesse zu ermöglichen. Todesfälle, die durch OOM-Killer verursacht wurden, treten asynchron auf, selbst bei Programmen, die mit der Speicherzuweisung verantwortungsbewusst umgehen. Ich persönlich hasse systemweites Overcommit im Allgemeinen und den Oom-Killer im Besonderen - es fördert einen teuflischen Ansatz für die Speicherverwaltung, der Bibliotheken infiziert und über sie jede App, die sie verwendet.
Ich würde vorschlagen, das Verhältnis auf 100 zu setzen und auch eine Swap-Partition zu haben, die im Allgemeinen nur von riesigen Prozessen genutzt wird - die oft nur einen winzigen Bruchteil des Teils von sich selbst verwenden, der in Swap gestopft wird, und somit Schützen Sie die überwiegende Mehrheit der Prozesse vor dem OOM-Killer-Fehler. Dies sollte Ihren Webserver vor dem zufälligen Tod schützen, und wenn er für den malloc
verantwortungsvollen Umgang geschrieben wurde , sogar vor dem Selbstmord (aber wetten Sie nicht auf Letzteres).
Das heißt, ich benutze dies in /etc/sysctl.d/10-no-overcommit.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 100