TL; DR
Kurz vorübergehend / Antwort
- Am einfachsten : Verwenden Sie eine kleinere Swap-Partition, und vermeiden Sie, dass der Kernel versucht, der Lüge gerecht zu werden, dass es keine Speicherbeschränkung gibt, indem Sie Prozesse aus langsamen Speichern ausführen.
- Bei einem großen Tausch wird der OOM (Out-of-Memory-Manager) nicht früh genug ausgeführt. Normalerweise hängt es vom virtuellen Speicher ab und hat meiner Erfahrung nach die Dinge nicht getötet, bis der gesamte Swap voll war, daher das Thrashing- und Crawling-System ...
- Brauchen Sie einen großen Swap für den Winterschlaf?
- Versucht / problematisch : Stellen Sie einige Grenzwerte ein (z. B. überprüfen Sie
ulimit -v
, und setzen Sie möglicherweise ein hartes oder weiches Limit mithilfe der as
Option in limits.conf
). Früher hat dies gut funktioniert, aber dank der Einführung von WebKit gigacage
erwarten viele Gnome-Apps jetzt unbegrenzte Adressräume und können nicht ausgeführt werden!
- Versuchte / problematisch : Die overcommit Politik und das Verhältnis eine andere Art und Weise zu verwalten , zu versuchen und zu mildern diese (zB
sysctl vm.overcommit_memory
, sysctl vm.overcommit_ratio
aber dieser Ansatz nicht für mich funktioniert.
- Schwierig / kompliziert : Versuchen Sie, den wichtigsten Prozessen (z. B. ssh) eine cgroup-Priorität zuzuweisen, aber dies scheint derzeit für cgroup v1 umständlich zu sein (hoffentlich wird es mit v2 einfacher) ...
Ich fand auch:
Längerfristige Lösung
Warten Sie und hoffen Sie, dass einige Upstream-Patches in stabile Distributionskerne gelangen. Hoffen Sie auch, dass die Distributoren die Kernel-Standardeinstellungen besser anpassen und die systemd-cgroups besser nutzen, um die Reaktionsfähigkeit der Benutzeroberfläche in Desktop-Editionen zu priorisieren.
Einige interessante Patches:
Es liegt also nicht nur an schlechtem User Space Code und Distro Config / Defaults, sondern auch daran, dass der Kernel damit besser umgehen kann.
Kommentare zu bereits berücksichtigten Optionen
1) Deaktivieren Sie den Swap
Es wird empfohlen, mindestens eine kleine Swap-Partition vorzusehen ( Brauchen wir auf modernen Systemen wirklich einen Swap? ). Das Deaktivieren von Swap verhindert nicht nur das Auslagern nicht verwendeter Seiten, sondern wirkt sich auch auf die standardmäßige heuristische Überlastungsstrategie des Kernels für die Speicherzuweisung aus ( Was bedeuten Heuristiken in Overcommit_memory = 0? ), Da diese Heuristik für Auslagerungsseiten zählt. Ohne Swap kann Overcommit wahrscheinlich immer noch im heuristischen Modus (0) oder im Always-Modus (1) funktionieren, aber die Kombination aus No-Swap und Never-Overcommit-Strategie (2) ist wahrscheinlich eine schreckliche Idee. Daher wird in den meisten Fällen kein Swap die Performance beeinträchtigen.
Denken Sie beispielsweise an einen Prozess mit langer Laufzeit, der zunächst den Speicher für einmalige Arbeiten berührt, diesen Speicher dann jedoch nicht freigibt und den Hintergrund weiterhin ausführt. Der Kernel muss dafür RAM verwenden, bis der Prozess endet. Ohne Tausch kann der Kernel keine Seite für etwas anderes erstellen, das den Arbeitsspeicher tatsächlich aktiv nutzen möchte. Denken Sie auch daran, wie viele Entwickler faul sind und nach der Verwendung nicht explizit Speicher freigeben.
3) Stellen Sie ein maximales Speicherlimit ein
Es gilt nur pro Prozess, und es ist wahrscheinlich eine vernünftige Annahme, dass ein Prozess nicht mehr Speicher anfordern sollte, als ein System physisch hat! So ist es wahrscheinlich nützlich, einen einsamen verrückten Prozess davon abzuhalten, Thrashing auszulösen, während er noch großzügig eingestellt ist.
4) Wichtige Programme (X11, bash, kill, top, ...) im Speicher behalten und niemals austauschen
Gute Idee, aber dann werden diese Programme den Speicher sprengen, den sie nicht aktiv nutzen. Es kann akzeptabel sein, wenn das Programm nur eine bescheidene Speichermenge anfordert.
Das Release von systemd 232 hat gerade einige Optionen hinzugefügt, die dies ermöglichen: Ich denke, man könnte mit 'MemorySwapMax = 0' verhindern, dass eine Einheit (ein Dienst) wie ssh irgendeinen Speicher auslagert.
Es wäre jedoch besser, den Speicherzugriff priorisieren zu können.
Lange Erklärung
Der Linux-Kernel ist besser auf Server-Workloads abgestimmt, sodass die Reaktionsfähigkeit der Benutzeroberfläche leider nur eine untergeordnete Rolle spielt. Es entspricht sogar den Standardeinstellungen in RHEL / CentOS 7.2, die normalerweise als Server verwendet werden.
OOM, Ulimit und Kompromiss zwischen Integrität und Reaktionsfähigkeit
Swap-Thrashing (wenn die Arbeitsspeichermenge, dh die Seiten, die in einem bestimmten kurzen Zeitraum gelesen und beschrieben werden, den physischen Arbeitsspeicher überschreiten) sperrt immer die Speicher-E / A - kein Kernel-Assistent kann ein System davon abspeichern, ohne einen Prozess zu beenden oder zwei...
Ich hoffe, dass Linux-OOM-Optimierungen in neueren Kerneln erkennen, dass dieser Arbeitssatz die physische Speichersituation überschreitet und einen Prozess abbricht. Wenn dies nicht der Fall ist, tritt das Thrashing-Problem auf. Das Problem ist, dass es bei einer großen Swap-Partition so aussehen kann, als ob das System noch Headroom hat, während der Kernel fröhlich Commits ausführt und weiterhin Speicheranforderungen bedient, aber die Arbeitsgruppe könnte in Swap übergehen und effektiv versuchen, den Speicher so zu behandeln, als ob Es ist RAM.
Auf Servern akzeptiert es die Performance-Einbußen, wenn für einen entschlossenen, langsamen, nicht verlorenen Daten-Kompromiss gekämpft wird. Auf Desktops ist der Kompromiss unterschiedlich, und Benutzer würden einen Datenverlust (Prozessopfer) vorziehen, um die Reaktionsfähigkeit zu gewährleisten.
Dies war eine nette komische Analogie zu OOM: oom_pardon, aka töte mein xlock nicht
Übrigens OOMScoreAdjust
wird eine weitere systembezogene Option zur Gewichtsreduzierung und Vermeidung von OOM-Tötungsprozessen als wichtiger angesehen.
gepuffertes Rückschreiben
Ich denke, " Hintergrund-Rückschreiben nicht saugen lassen " hilft, einige Probleme zu vermeiden, bei denen ein Prozess, der den RAM überlastet, ein weiteres Auslagern (Schreiben auf die Festplatte) verursacht und der Bulk-Schreibvorgang auf die Festplatte alles andere blockiert, was E / A benötigt. Es ist nicht das eigentliche Problem, das die Ursache für das Thrashen ist, aber es trägt zur allgemeinen Verschlechterung der Reaktionsfähigkeit bei.
Begrenzung
Ein Problem bei ulimits besteht darin, dass für den Adressraum des virtuellen Speichers eine Beschränkung gilt (was das Kombinieren von physischem und Swap-Raum impliziert). Wie pro man limits.conf
:
rss
maximum resident set size (KB) (Ignored in Linux 2.4.30 and
higher)
Das Setzen eines ulimits, das nur auf die physische RAM-Nutzung angewendet wird, scheint also nicht mehr verwendbar zu sein. Daher
as
address space limit (KB)
scheint das einzig angesehene tunable zu sein.
Leider können einige Anwendungen nicht ausgeführt werden, wie am Beispiel von WebKit / Gnome näher erläutert wird, wenn die Zuweisung des virtuellen Adressraums begrenzt ist.
cgroups soll in zukunft helfen?
Derzeit scheint es umständlich, aber möglich, einige Kernel-cgroup-Flags zu aktivieren cgroup_enable=memory swapaccount=1
(z. B. in grub config) und dann den cgroup-Speichercontroller zu verwenden, um die Speichernutzung zu begrenzen.
cgroups verfügen über erweiterte Speicherbegrenzungsfunktionen als die Optionen 'ulimit'. CGroup v2 gibt Hinweise auf Versuche, die Funktionsweise von ulimits zu verbessern.
Die kombinierte Speicher- und Swap-Abrechnung und -Begrenzung wird durch eine echte Kontrolle über den Swap-Bereich ersetzt.
CGroup-Optionen können über systemd-Ressourcensteuerungsoptionen festgelegt werden . Z.B:
Andere nützliche Optionen könnten sein
Diese haben einige Nachteile:
- Overhead. In der aktuellen Docker-Dokumentation wird kurz 1% zusätzliche Speichernutzung und 10% Leistungseinbußen erwähnt (wahrscheinlich im Hinblick auf Speicherzuweisungsvorgänge - es wird nicht wirklich angegeben).
- Das Cgroup / Systemd-Zeug wurde in letzter Zeit stark überarbeitet, so dass die Linux-Distributoren aufgrund des Upstream-Flusses möglicherweise darauf warten, dass es sich als erstes erledigt.
In CGroup v2 wird empfohlen , memory.high
die Speichernutzung einer Prozessgruppe zu drosseln und zu verwalten. Dieses Zitat legt jedoch nahe, dass das Überwachen von Speicherdrucksituationen mehr Arbeit erforderte (ab 2015).
Ein Maß für den Speicherdruck - wie stark die Arbeitslast aufgrund von Speichermangel beeinträchtigt wird - ist erforderlich, um festzustellen, ob eine Arbeitslast mehr Speicher benötigt. Leider ist der Mechanismus zur Überwachung des Speicherdrucks noch nicht implementiert.
Angesichts der Komplexität der User-Space-Tools von systemd und cgroup habe ich keinen einfachen Weg gefunden, um etwas Angemessenes festzulegen und dies weiter zu nutzen. Die Dokumentation zu cgroup und systemd für Ubuntu ist nicht großartig. Zukünftige Arbeiten sollten für Distributionen mit Desktop-Editionen die Nutzung von cgroups und systemd sein, damit ssh und die X-Server / Window-Manager-Komponenten unter hohem Speicherdruck vorrangig auf CPU, physischen RAM und Speicher-E / A zugreifen können, um nicht mit den Prozessen zu konkurrieren beschäftigt tauschen. Die CPU- und E / A-Prioritätsfunktionen des Kernels gibt es schon seit einiger Zeit. Es scheint ein vorrangiger Zugriff auf den physischen Arbeitsspeicher zu sein, der fehlt.
Allerdings sind auch CPU- und IO-Prioritäten nicht richtig eingestellt !? Als ich die systemd cgroup-Limits, CPU-Freigaben usw. überprüfte, hatte Ubuntu, soweit ich sehen konnte, keine vordefinierten Priorisierungen vorgenommen. ZB lief ich:
systemctl show dev-mapper-Ubuntu\x2dswap.swap
Ich habe das mit der gleichen Ausgabe für ssh, samba, gdm und nginx verglichen. Wichtige Dinge wie die grafische Benutzeroberfläche und die Remote-Administrationskonsole müssen beim Thrashen gleichermaßen mit allen anderen Prozessen kämpfen.
Beispielspeicherbeschränkungen, die ich auf einem 16GB RAM System habe
Ich wollte den Ruhezustand aktivieren, also brauchte ich eine große Swap-Partition. Daher versuchen, mit ulimits usw. zu mildern.
ulimit
Ich habe * hard as 16777216
in /etc/security/limits.d/mem.conf
so dass kein einzelner Prozess erlaubt würde mehr Speicher anzufordern , als physikalisch möglich ist. Ich werde nicht verhindern, dass alle zusammen verprügelt werden, aber ohne kann nur ein einziger Prozess mit gieriger Speichernutzung oder einem Speicherverlust zu Verprügelungen führen. ZB habe ich gesehen gnome-contacts
, wie 8 GB + Arbeitsspeicher aufgebraucht wurden, wenn alltägliche Dinge wie das Aktualisieren der globalen Adressliste von einem Exchange-Server aus durchgeführt wurden ...
Wie man sieht ulimit -S -v
, haben viele Distributionen dieses Hard- und Soft-Limit als "unbegrenzt" festgelegt. Theoretisch könnte ein Prozess viel Speicher anfordern, aber nur aktiv eine Teilmenge verwenden und glücklich davon ausgehen, dass 24 GB RAM zur Verfügung stehen Das System hat nur 16 GB. Das obige harte Limit führt dazu, dass Prozesse, die möglicherweise fehlerfrei ausgeführt wurden, abgebrochen werden, wenn der Kernel seine gierigen spekulativen Speicheranforderungen ablehnt.
Es werden jedoch auch verrückte Dinge wie Gnomenkontakte abgefangen, und anstatt die Reaktionsfähigkeit meines Desktops zu verlieren, wird der Fehler "Nicht genügend freier Speicher" angezeigt:
Komplikationen beim Setzen des ulimit für den Adressraum (virtueller Speicher)
Leider geben manche Entwickler gerne vor, der virtuelle Speicher sei eine unendliche Ressource, und das Setzen eines Grenzwerts für den virtuellen Speicher kann einige Apps beschädigen. ZB WebKit (von dem einige Gnome-Apps abhängen) hat eine gigacage
Sicherheitsfunktion hinzugefügt, die versucht, verrückte Mengen an virtuellem Speicher zuzuweisen, und FATAL: Could not allocate gigacage memory
Fehler mit einem frechen Hinweis Make sure you have not set a virtual memory limit
passieren. Die Umgehung,GIGACAGE_ENABLED=no
Der Verzicht auf die Sicherheitsvorteile, aber auch der Verzicht auf ein Sicherheitsmerkmal (z. B. eine Ressourcensteuerung, die Denial-of-Service verhindern kann), ohne die Zuweisung von virtuellem Speicher einschränken zu dürfen. Ironischerweise scheinen sie zwischen Gigacage- und Gnome-Entwicklern zu vergessen, dass die Begrenzung der Speicherzuweisung selbst eine Sicherheitskontrolle ist. Und leider ist mir aufgefallen, dass die Gnome-Apps, die auf Gigacage basieren, keine explizite Anforderung eines höheren Limits haben, sodass in diesem Fall sogar ein weiches Limit die Dinge kaputt macht.
Um ehrlich zu sein, wäre es weniger gefährlich, wenn der Kernel die Speicherzuweisung auf der Grundlage der Nutzung des residenten Speichers anstelle des virtuellen Speichers ablehnen könnte.
überbeanspruchen
Wenn Sie es vorziehen, Anwendungen den Speicherzugriff zu verweigern und das Overcommitting zu beenden, testen Sie mit den folgenden Befehlen, wie sich Ihr System bei hohem Speicherdruck verhält.
In meinem Fall war das Standard-Commit-Verhältnis:
$ sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50
Sie wird jedoch erst dann vollständig wirksam, wenn Sie die Richtlinie ändern, um das Overcommiting zu deaktivieren und das Verhältnis anzuwenden
sudo sysctl -w vm.overcommit_memory=2
Dem implizierten Verhältnis konnten insgesamt nur 24 GB Speicher zugewiesen werden (16 GB RAM * 0,5 + 16 GB SWAP). Daher wird OOM wahrscheinlich nie angezeigt, und es ist weniger wahrscheinlich, dass Prozesse beim Auslagern ständig auf den Speicher zugreifen. Aber ich werde wahrscheinlich auch die Gesamtsystemeffizienz opfern.
Dies führt dazu, dass viele Anwendungen abstürzen, da Entwickler das Betriebssystem, das eine Speicherzuweisungsanforderung ablehnt, häufig nicht ordnungsgemäß verarbeiten. Das gelegentliche Risiko eines langwierigen Absturzes aufgrund von Thrashing (Verlust all Ihrer Arbeit nach einem Hard-Reset) wird gegen das häufigere Risiko eines Absturzes verschiedener Apps eingetauscht. In meinen Tests hat es nicht viel geholfen, da der Desktop selbst abstürzte, wenn das System unter Speicherdruck stand und Speicher nicht zugewiesen werden konnte. Zumindest Konsolen und SSH funktionierten jedoch noch.
Weitere Informationen zur Funktionsweise von VM-Overcommit-Speicher finden Sie hier.
Da sudo sysctl -w vm.overcommit_memory=0
der gesamte grafische Desktop-Stapel und die darin enthaltenen Anwendungen dennoch abstürzen, habe ich mich dafür entschieden, die Standardeinstellungen wiederherzustellen.