Hmm, ich bin nicht ganz überzeugt von Argumenten für Overcommit und OOM-Killer ... Wenn Womble schreibt,
"Der OOM-Killer ist nur dann verheerend, wenn Sie Ihr System überlastet haben. Geben Sie ihm genügend Swap, und führen Sie keine Anwendungen aus, die sich plötzlich dazu entschließen, große Mengen an RAM zu verbrauchen, und Sie werden kein Problem haben."
Er beschreibt ein Umgebungsszenario, in dem Overcommit und OOM-Killer nicht erzwungen werden oder nicht "wirklich" agieren (wenn allen Anwendungen nach Bedarf Speicher zugewiesen wird und genügend virtueller Speicher zugewiesen werden kann, folgen die Speicherschreibvorgänge genau den Speicherzuweisungen ohne Fehler, so dass wir nicht wirklich über ein überlastetes System sprechen könnten, selbst wenn eine Überlastungsstrategie aktiviert wäre). Es geht um eine implizite Annahme, dass Overcommit und OOM-Killer am besten funktionieren, wenn ihre Intervention nicht benötigt wird. Soweit ich das beurteilen kann (und ich gebe zu, dass ich nicht viel sagen kann ...), teilen das die meisten Befürworter dieser Strategie. Wenn ich mich außerdem auf Anwendungen mit bestimmten Verhaltensweisen beziehe, wenn Speicher vorab zugewiesen wird, denke ich, dass eine bestimmte Behandlung auf Verteilungsebene optimiert werden könnte, anstatt eine Standardeinstellung zu haben.
Für welche Anliegen der JVM, na ja, es ist eine virtuelle Maschine zu einem gewissen Grad muss es alle Ressourcen zuzuteilen es muss beim Start, so kann es seine ‚falsche‘ Umgebung für seine Anwendungen erstellen, und halten Sie die verfügbaren Ressourcen vom Host getrennt Umwelt, so weit wie möglich. Daher ist es möglicherweise vorzuziehen, wenn der Startvorgang fehlschlägt, anstatt nach einer bestimmten Zeit als Folge eines „externen“ OOM-Zustands (verursacht durch einen Overcommit / OOM-Killer / was auch immer) oder wenn ein solcher Zustand seine eigenen Probleme verursacht Interne OOM-Handlungsstrategien (im Allgemeinen sollte eine VM die erforderlichen Ressourcen von Anfang an erhalten und das Hostsystem sollte sie bis zum Ende ignorieren), so wie es eine beliebige Menge an physischem RAM, die mit einer Grafikkarte geteilt wird, niemals ist - und nicht sein kann - vom Betriebssystem berührt).
In Bezug auf Apache bezweifle ich, dass es besser ist, den gesamten Server gelegentlich zu töten und neu zu starten, als zuzulassen, dass ein einzelnes Kind zusammen mit einer einzelnen Verbindung von Anfang an (= der des Kindes / der Verbindung) ausfällt (als wäre es eine ganz neue Instanz von die JVM, die nach einer Weile ausgeführt wurde). Ich denke, die beste "Lösung" hängt von einem bestimmten Kontext ab. Wenn Sie beispielsweise einen E-Commerce-Dienst in Betracht ziehen, ist es möglicherweise weitaus besser, wenn manchmal einige Verbindungen zu einem Einkaufsdiagramm nicht zufällig hergestellt werden können, anstatt den gesamten Dienst zu verlieren. Dies birgt beispielsweise das Risiko, eine laufende Auftragsabwicklung zu unterbrechen (vielleicht noch schlimmer) ein Bezahlungsprozess mit allen Konsequenzen des Falls
Ebenso kann auf einer Workstation der Prozess, der die meisten Ressourcen verbraucht und daher für den OOM-Killer die erste Wahl ist, eine speicherintensive Anwendung sein, wie z. B. ein Video-Transcoder oder eine Rendering-Software, wahrscheinlich die einzige Anwendung der Benutzer möchte unberührt bleiben. Diese Überlegungen deuten darauf hin, dass die OOM-Killer-Standardrichtlinie zu aggressiv ist. Es wird ein "Worst - Fit" - Ansatz verwendet, der dem einiger Dateisysteme ähnelt (das OOMK versucht, so viel Speicher wie möglich freizugeben und gleichzeitig die Anzahl der getöteten Unterprozesse zu verringern, um weitere Eingriffe in kurzer Zeit zu verhindern) Außerdem kann eine fs mehr Speicherplatz zuweisen, als tatsächlich für eine bestimmte Datei benötigt wird, um eine weitere Zuweisung zu verhindern, wenn die Datei größer wird, und so die Fragmentierung in gewissem Maße zu verhindern.
Ich bin jedoch der Meinung, dass eine umgekehrte Strategie, wie ein "Best-Fit" -Ansatz, vorzuziehen sein könnte, um genau den Speicher freizugeben, der zu einem bestimmten Zeitpunkt benötigt wird, und sich nicht mit "großen" Prozessen zu beschäftigen, die durchaus verschwenden könnten Speicher, aber möglicherweise auch nicht, und der Kernel kann das nicht wissen (hmm, ich kann mir vorstellen, dass das Verfolgen der Seitenzugriffe und der Zeit darauf hindeuten kann, dass ein Prozess Speicher zuweist, den er nicht mehr benötigt, um zu erraten, ob ein Prozess vorhanden ist Speicher verschwenden oder nur viel verbrauchen, aber Zugriffsverzögerungen sollten in CPU-Zyklen gewichtet werden, um eine Speicherverschwendung von einer speicher- und CPU-intensiven Anwendung zu unterscheiden. Eine solche Heuristik kann jedoch möglicherweise ungenau sein und einen übermäßigen Overhead verursachen.
Darüber hinaus ist es möglicherweise nicht richtig, dass das Beenden der weniger möglichen Prozesse immer eine gute Wahl ist. In einer Desktop-Umgebung (zum Beispiel ein Nettop oder ein Netbook mit begrenzten Ressourcen) kann ein Benutzer beispielsweise einen Browser mit mehreren Registerkarten ausführen. , sowie einige andere Anwendungen (ein Textverarbeitungsprogramm mit nicht gespeicherten Daten, ein Mail-Client, ein PDF-Reader, ein Media-Player, ...), sowie einige (System-) Dämonen und einige Dateimanager-Instanzen. Jetzt tritt ein OOM-Fehler auf, und der OOMK entscheidet sich dafür, den Browser zu beenden, während der Benutzer etwas tut, das über das Netz als "wichtig" erachtet wird. Der Benutzer wäre enttäuscht. Auf der anderen Seite schließen die wenigen Dateimanager '
Ich denke jedenfalls, dass der Benutzer in die Lage versetzt werden sollte, selbst zu entscheiden, was zu tun ist. In einem Desktop (= interaktiven) System sollte dies relativ einfach zu bewerkstelligen sein, vorausgesetzt, es sind genügend Ressourcen reserviert, um den Benutzer aufzufordern, eine Anwendung zu schließen (aber auch das Schließen einiger Registerkarten könnte ausreichen) und seine Wahl zu treffen (eine Option könnte dies sein) besteht darin, eine zusätzliche Auslagerungsdatei zu erstellen, wenn genügend Speicherplatz vorhanden ist. Für Services (und im Allgemeinen) würde ich auch zwei weitere mögliche Verbesserungen in Betracht ziehen: Eine protokolliert OOM-Killer-Interventionen sowie Prozesse, die Fehler starten / forken, sodass der Fehler leicht behoben werden kann (z. B. eine API) Informieren Sie den Prozess, der den neuen Prozess erstellt oder das Forken durchführt. Ein Server wie Apache mit einem korrekten Patch kann daher eine bessere Protokollierung für bestimmte Fehler bieten. Dies könnte unabhängig davon geschehen, dass das Overcommit / OOMK aktiv ist. Zweitens könnte ein Mechanismus zur Feinabstimmung des OOMK-Algorithmus eingerichtet werden, der jedoch nicht von Bedeutung ist. Ich weiß, dass es bis zu einem gewissen Grad möglich ist, eine bestimmte Richtlinie prozessweise zu definieren, aber ich möchte a 'zentralisierter' Konfigurationsmechanismus, basierend auf einer oder mehreren Listen von Anwendungsnamen (oder IDs), um relevante Prozesse zu identifizieren und ihnen einen bestimmten Grad an Wichtigkeit zu verleihen (gemäß den aufgelisteten Attributen); Ein solcher Mechanismus sollte (oder könnte zumindest) auch geschichtet sein, so dass es eine benutzerdefinierte Liste auf oberster Ebene, eine system- (verteilungs-) definierte Liste und (unterste Ebene) anwendungsdefinierte Einträge geben kann Beispielsweise könnte ein DE-Dateimanager das OOMK anweisen, jede Instanz sicher zu töten.
Darüber hinaus könnte eine API bereitgestellt werden, die es Anwendungen ermöglicht, ihren "Wichtigkeitsgrad" zur Laufzeit zu erhöhen oder zu verringern (in Bezug auf Speicherverwaltungszwecke und unabhängig von der Ausführungspriorität), so dass beispielsweise eine Textverarbeitung beginnen könnte eine niedrige 'Wichtigkeit', aber erhöhen Sie sie, da einige Daten vor dem Löschen in eine Datei oder dem Ausführen einer Schreiboperation gehalten werden, und verringern Sie die Wichtigkeit erneut, wenn eine solche Operation endet (analog dazu könnte ein Dateimanager die Ebene ändern, wenn sie von gerade abgelaufen ist Wenn Sie Dateien für den Umgang mit Daten und umgekehrt bereitstellen, anstatt separate Prozesse zu verwenden, kann Apache verschiedenen Kindern unterschiedliche Wichtigkeitsstufen zuweisen oder einen untergeordneten Status gemäß einer Richtlinie ändern, die von Sysadmins festgelegt und über Apaches - oder eine andere Art von Servern - verfügbar gemacht wird - die Einstellungen). Na sicher, Eine solche API könnte und würde missbraucht / missbraucht werden, aber ich denke, das ist ein geringes Problem im Vergleich zum Kernel, der Prozesse abbricht, um Speicher freizugeben, ohne relevante Informationen darüber, was auf dem System vor sich geht (und Speicherbedarf / Erstellungszeit oder Ähnliches) Für mich nicht relevant oder "validierend") - nur Benutzer, Administratoren und Programmierer können wirklich feststellen, ob ein Prozess aus irgendeinem Grund "noch benötigt" wird, was der Grund ist und / oder ob sich die Anwendung in einem führenden Status befindet zu Datenverlust oder anderen Schäden / Problemen, wenn sie getötet werden; Es könnte jedoch noch eine gewisse Annahme getroffen werden, zum Beispiel, dass nach Ressourcen einer bestimmten Art (Dateideskriptoren, Netzwerksockets usw.) gesucht wird, die von einem Prozess erfasst wurden und bei ausstehenden Vorgängen festgestellt werden kann, ob sich ein Prozess in einem höheren Status als befindet der eine satz,
Oder vermeiden Sie einfach eine Überbeanspruchung, und lassen Sie den Kernel genau das tun, was ein Kernel tun muss, indem Sie Ressourcen zuweisen (aber nicht willkürlich wie der OOM-Killer retten), Prozesse planen, Hunger und Deadlocks verhindern (oder aus ihnen retten) und die vollständige Verfügbarkeit sicherstellen Speicherplatztrennung und so weiter ...
Ich würde auch noch ein paar Worte über Overcommit-Ansätze verlieren. Aus anderen Diskussionen habe ich den Gedanken gewonnen, dass eines der Hauptprobleme bei Überbeanspruchungen (sowohl als Grund, es zu wollen, als auch als Quelle möglicher Probleme) in der Handhabung von Gabeln besteht: Ehrlich gesagt, ich weiß nicht, wie genau die Kopie ist. Die On-Write-Strategie wird implementiert, aber ich denke, dass aggressive (oder optimistische) Richtlinien durch eine Swap-ähnliche Lokalitätsstrategie gemildert werden könnten. Das heißt, anstatt nur gegabelte Prozesscodeseiten und Planungsstrukturen zu klonen (und anzupassen), könnten einige andere Datenseiten vor einem tatsächlichen Schreibvorgang kopiert werden, wobei unter den Seiten ausgewählt wird, auf die der übergeordnete Prozess zugegriffen hat, um häufiger zu schreiben (d. H. Verwenden eines Zählers für Schreiboperationen).
Alles natürlich, IMHO.