Lösung 1:
Einstellung overcommit_ratio
bis 80 ist wahrscheinlich nicht die richtige Aktion. Wenn Sie den Wert auf einen Wert unter 100 setzen, ist das fast immer falsch.
Der Grund dafür ist, dass Linux-Anwendungen mehr zuweisen, als sie wirklich benötigen. Angenommen, sie weisen 8 KB zu, um eine Textzeichenfolge aus zwei Zeichen zu speichern. Nun, das sind mehrere KB, die genau dort ungenutzt sind. Anwendungen tun dies häufig, und dafür wurde Overcommit entwickelt.
Mit Overcommit bei 100 erlaubt der Kernel also im Grunde nicht, dass Anwendungen mehr Speicher zuweisen, als Sie haben (Swap + RAM). Wenn Sie es auf weniger als 100 einstellen, werden Sie nie Ihren gesamten Speicher verwenden. Wenn Sie diese Einstellung festlegen, sollten Sie sie aufgrund des oben erwähnten Szenarios, das ziemlich häufig vorkommt, höher als 100 festlegen.
Nun, was Ihr Problem mit dem Auslösen des OOM-Killers betrifft, wird das manuelle Festlegen von Overcommit dies wahrscheinlich nicht beheben. Die Standardeinstellung (heuristische Bestimmung) ist ziemlich intelligent.
Wenn Sie sehen möchten, ob dies wirklich die Ursache des Problems ist, sehen Sie sich /proc/meminfo
an wenn der OOM-Killer läuft. Wenn Sie diesen Committed_AS
sehen liegt nahe bei CommitLimit
, aber free
immer noch freien verfügbaren Speicher anzeigt, dann können Sie das Overcommit für Ihr Szenario manuell anpassen. Wenn Sie diesen Wert zu niedrig einstellen, beginnt der OOM-Killer, Anwendungen zu beenden, wenn Sie noch genügend Speicher frei haben. Eine zu hohe Einstellung kann dazu führen, dass zufällige Anwendungen sterben, wenn sie versuchen, Speicher zu verwenden, der ihnen zugewiesen wurde, aber tatsächlich nicht verfügbar ist (wenn der gesamte Speicher tatsächlich aufgebraucht ist).
Lösung 2:
Abschnitt 9.6 „Overcommit und OOM“ in dem Dokument, das @dunxd erwähnt, ist besonders anschaulich zu den Gefahren des Zulassens von Overcommit. Allerdings ist die 80
sah für mich auch interessant aus, also habe ich ein paar Tests durchgeführt.
Was ich gefunden habe ist, dass die overcommit_ratio
wirkt sich auf den gesamten für ALLE Prozesse verfügbaren Arbeitsspeicher aus. Root-Prozesse scheinen nicht anders behandelt zu werden als normale Benutzerprozesse.
Einstellen des Verhältnisses auf 100
oder weniger sollte die klassische Semantik bereitstellen, bei der Werte von malloc/sbrk
zurückgegeben werden sind zuverlässig. Stellen Sie die Verhältnisse niedriger als 100
ein könnte eine Möglichkeit sein, mehr RAM für prozessfremde Aktivitäten wie Caching usw. zu reservieren.
Also, auf meinem Computer mit 24 GiB RAM, mit deaktiviertem Swap, 9 GiB in Verwendung, mit top
zeigt
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 schnappen konnte (Berührung jeder Seite) - in jedem Fall wurde das Programm einmal sauber beendet malloc
fehlgeschlagen.
50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
Das gleichzeitige Ausführen mehrerer Geräte, selbst mit einigen als Root-Benutzer, änderte nichts an der Gesamtmenge, die sie zusammen verbrauchten. Es ist interessant, dass es die letzten 3+ GiB oder so nicht verbrauchen konnte; die free
fiel nicht viel unter das, was hier gezeigt wird:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
Die Experimente waren chaotisch - alles, was malloc in dem Moment verwendet, in dem der gesamte RAM verwendet wird, neigt zum Absturz, da viele Programmierer schlecht darin sind, in C nach malloc-Fehlern zu suchen, einige beliebte Sammlungsbibliotheken es vollständig ignorieren und C++ und verschiedene andere Sprachen sogar sind schlimmer.
Die meisten der frühen Implementierungen von imaginärem RAM, die ich gesehen habe, sollten einen sehr speziellen Fall handhaben, in dem ein einzelner großer Prozess – sagen wir 51 %+ des verfügbaren Speichers – fork()
benötigte um exec()
irgendein Förderprogramm, normalerweise ein viel, viel kleineres. Betriebssysteme mit Copy-on-Write-Semantik würden den fork()
zulassen , aber mit der Maßgabe, dass, wenn der gegabelte Prozess tatsächlich versuchen würde, zu viele Speicherseiten zu ändern (von denen jede dann als neue Seite unabhängig vom anfänglichen riesigen Prozess instanziiert werden müsste), er am Ende getötet würde. Der übergeordnete Prozess war nur dann in Gefahr, wenn er mehr Speicher zuordnete, und konnte mit dem Auslaufen fertig werden, in einigen Fällen nur, indem er eine Weile wartete, bis ein anderer Prozess starb, und dann fortfuhr. Der untergeordnete Prozess hat sich normalerweise einfach durch ein (normalerweise kleineres) Programm über exec()
ersetzt und war dann frei von dem Vorbehalt.
Das Overcommit-Konzept von Linux ist ein extremer Ansatz, um sowohl den fork()
auftreten und einzelne Prozesse massiv überlasten können. Todesfälle durch OOM-Killer treten asynchron auf, selbst bei Programmen, die dies tun Gehen Sie verantwortungsvoll mit der Speicherzuweisung um. Ich persönlich hasse systemweit Overcommit im Allgemeinen und den Oom-Killer im Besonderen - es fördert einen teuflischen Ansatz zur Speicherverwaltung, der Bibliotheken und durch sie jede App, die sie verwendet, infiziert.
Ich würde vorschlagen, das Verhältnis auf 100 zu setzen und auch eine Swap-Partition zu haben, die im Allgemeinen nur von großen Prozessen verwendet 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-Fehlfunktion. Dies sollte Ihren Webserver vor zufälligem Tod schützen und wenn er so geschrieben wurde, dass er mit malloc
umgehen kann verantwortungsbewusst, sogar sicher davor, sich umzubringen (aber wetten Sie nicht auf letzteres).
Das heißt, ich verwende dies in /etc/sysctl.d/10-no-overcommit.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 100