TL; DR
Kurzzeit / Antwort
- Am einfachsten : Haben Sie eine kleinere Swap-Partition und vermeiden Sie, dass der Kernel versucht, der Lüge nachzukommen, dass es keine Speicherbegrenzung gibt, indem Prozesse aus langsamem Speicher ausgeführt werden.
- Bei einem großen Swap greift der OOM (Out of Memory Manager) nicht schnell genug ein. Normalerweise rechnet es nach virtuellem Speicher und hat in meiner bisherigen Erfahrung keine Dinge getötet, bis der gesamte Swap gefüllt war, daher das System des Dreschens und Krieges ...
- Brauchen Sie einen großen Swap für den Winterschlaf?
- Versucht / Problematisch : Legen Sie einige ulimits fest (z. B. prüfen Sie
ulimit -v
mit deras
Option in ein hartes oder weiches Limitlimits.conf
). Früher hat das gut funktioniert, aber dank der Einführung von WebKitgigacage
erwarten viele gnome-Apps jetzt unbegrenzte Adressräume und laufen nicht! - 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, die wichtigsten Prozesse (z. B. ssh) mit einer cgroup-Priorität zu versehen. Dies scheint jedoch derzeit für cgroup v1 umständlich zu sein (hoffentlich wird v2 es einfacher machen) ...
- Versucht / Problematisch : Legen Sie einige ulimits fest (z. B. prüfen Sie
Ich habe auch gefunden:
- ein weiterer Stack-Tauscheintrag, der den obigen Hinweis für kleinere Swap-Räume bestätigt .
- Sie könnten etwas wie Thrash-Protect als Umgehungslösung für die aktuelle Situation versuchen .
Längerfristige Lösung
Warten Sie und hoffen Sie auf einige Upstream-Patches, um stabile Distributionskerne zu erreichen. Ich hoffe auch, dass Distributoren die Kernel-Standardeinstellungen besser abstimmen und systemd cgroups besser einsetzen, um die GUI-Reaktionsfähigkeit in Desktop-Editionen zu priorisieren.
Einige Flecken von Interesse:
Es liegt also nicht nur an schlechtem Benutzer-Space-Code und an den Distro-Config / Defaults - der Kernel könnte dies besser bewältigen.
Anmerkungen zu bereits berücksichtigten Optionen
1) Deaktivieren Sie den Swap
Es wird empfohlen, mindestens eine kleine Swap-Partition bereitzustellen ( Brauchen wir auf modernen Systemen wirklich einen Swap? ). Durch das Deaktivieren von Swap wird nicht nur das Auslagern nicht verwendeter Seiten verhindert, sondern es kann sich auch auf die Standardstrategie für die zu hohe Heuristik des Kernels für die Speicherzuordnung auswirken ( Was bedeutet Heuristik in Overcommit_memory = 0? ), Da diese Heuristik für Swap-Seiten gilt. Ohne Swap kann Overcommit wahrscheinlich immer noch in den heuristischen (0) oder immer (1) -Modi funktionieren, aber die Kombination von No Swap und der Never (2) Overcommit-Strategie ist wahrscheinlich eine schreckliche Idee. In den meisten Fällen wird also kein Swap die Performance beeinträchtigen.
Denken Sie beispielsweise an einen langwierigen Prozess, der anfänglich den Speicher für einmalige Arbeit berührt, diesen Speicher dann jedoch nicht freigibt und den Hintergrund weiterführt. Der Kernel muss dazu RAM verwenden, bis der Prozess beendet ist. Ohne Swap kann der Kernel nicht nach etwas anderem suchen, das RAM aktiv nutzen möchte. Denken Sie auch darüber nach, wie viele Entwickler faul sind und nach der Verwendung nicht explizit Speicherplatz freigeben.
3) Maximale Speichergröße einstellen
Dies gilt nur für einen Prozess, und es ist wahrscheinlich eine vernünftige Annahme, dass ein Prozess nicht mehr Speicher anfordert, als ein System physisch hat! Daher ist es wahrscheinlich nützlich, zu verhindern, dass ein einzelner verrückter Prozess Thrashing auslöst, während er dennoch großzügig eingestellt ist.
4) Bewahren Sie wichtige Programme (X11, bash, kill, top, ...) im Speicher auf und tauschen Sie diese niemals aus
Gute Idee, aber dann werden diese Programme Speicher beanspruchen, den sie nicht aktiv nutzen. Es kann akzeptabel sein, wenn das Programm nur eine bescheidene Speichermenge anfordert.
Systemd 232 hat gerade einige Optionen hinzugefügt, die dies möglich machen: Ich denke, man könnte "MemorySwapMax = 0" verwenden, um zu verhindern, dass ein Gerät (Dienst) wie ssh irgendeinen Speicher auslagert.
Es wäre jedoch besser, den Speicherzugriff priorisieren zu können.
Lange Erklärung
Der Linux-Kernel ist mehr auf Server-Workloads abgestimmt, so dass die GUI-Reaktionsfähigkeit leider ein zweitrangiges Problem war ... Die Einstellungen für die Kernel-Speicherverwaltung auf der Desktop-Edition von Ubuntu 16.04 LTS schienen sich nicht von den anderen Server-Editionen zu unterscheiden. Es stimmt sogar mit den Standardeinstellungen in RHEL / CentOS 7.2 überein, die normalerweise als Server verwendet werden.
OOM, ulimit und Kompromisslosigkeit gegen Reaktionsfähigkeit
Swap-Thrashing (wenn der Arbeitsspeicher, dh Seiten, die innerhalb eines bestimmten Zeitrahmens gelesen und beschrieben werden, den physischen RAM-Speicher überschreitet), wird die Speicher-E / A immer blockiert - keine Kernel-Zauberei kann ein System davon abhalten, ohne einen Prozess zu beenden oder zwei...
Ich hoffe, dass Linux-OOM-Optimierungen, die in neueren Kerneln auftauchen, erkennen, dass dieser Arbeitssatz den physischen Hauptspeicher übersteigt und einen Prozess abbricht. Wenn dies nicht der Fall ist, tritt das Thrash-Problem auf. Das Problem ist, mit einer großen Swap-Partition kann es so aussehen, als ob das System noch über Headroom verfügt, während der Kernel fröhlich übergeht und Speicheranforderungen abdeckt. Das Arbeitsset könnte jedoch in den Swap übergreifen und versuchen, den Speicher effektiv zu behandeln es ist RAM.
Auf Servern akzeptiert es die Leistungseinbußen des Thrashings für einen entschlossenen, langsamen, Datenverlust und Kompromiss. Auf Desktops ist der Kompromiss anders, und Benutzer würden ein wenig Datenverlust (Prozessopfer) vorziehen, um die Reaktionsfähigkeit zu erhalten.
Dies war eine nette komische Analogie über OOM: oom_pardon, aka töte nicht mein xlock
Übrigens OOMScoreAdjust
ist eine weitere systemd Option die Gewichtszunahme und das Vermeiden von OOM-Tötungsprozessen.
gepuffertes Rückschreiben
Ich denke, " Hintergrund-Rückschreiben nicht saugen lassen " wird dazu beitragen, einige Probleme zu vermeiden, bei denen ein Prozess, der den Arbeitsspeicher überlastet, einen anderen Auslagerungsvorgang verursacht (Write-to-Disk) und der Massen-Write-to-Disk-Vorgang alles andere blockiert, wenn IO gewünscht wird. Es ist nicht das eigentliche Problem der Ursache, aber es trägt zur allgemeinen Verschlechterung der Reaktionsfähigkeit bei.
Begrenzung
Ein Problem bei ulimits besteht darin, dass die Abrechnungsgrenze für den Adressraum des virtuellen Speichers gilt (was bedeutet, dass sowohl physischer als auch Swap-Bereich kombiniert werden). Wie pro man limits.conf
:
rss maximum resident set size (KB) (Ignored in Linux 2.4.30 and higher)
Das Festlegen eines ulimit, um nur auf die physische RAM-Nutzung anzuwenden, scheint daher nicht mehr brauchbar zu sein. Daher
as address space limit (KB)
scheint der einzig angesehene stimmbare zu sein.
Unglücklicherweise, wie ausführlicher am Beispiel von WebKit / Gnome beschrieben, können einige Anwendungen nicht ausgeführt werden, wenn die virtuelle Adressraumzuweisung begrenzt ist.
cgroups soll in Zukunft helfen?
Momentan scheint es umständlich zu sein, es ist jedoch möglich, einige Kernflags für cgroup zu aktivieren cgroup_enable=memory swapaccount=1
(z. B. in grub config) und dann den cgroup-Speichercontroller zu verwenden, um die Speicherbelegung zu begrenzen.
cgroups verfügen über erweiterte Speicherbegrenzungsfunktionen als die 'ulimit'-Optionen. Hinweise zu CGroup v2 weisen auf Versuche hin, die Funktionsweise von ulimits zu verbessern.
Die kombinierte Speicher- und Swap-Abrechnung und -Begrenzung wird durch die tatsächliche Kontrolle des Swap-Bereichs ersetzt.
CGroup-Optionen können über systemd-Ressourcensteuerungsoptionen festgelegt werden . Z.B:
- MemoryHigh
- MemoryMax
Andere nützliche Optionen könnten sein
- IOWeight
- CPUShares
Diese haben einige Nachteile:
- Overhead In der aktuellen Docker-Dokumentation wird kurz 1% zusätzlicher Speicherverbrauch und 10% Leistungseinbußen erwähnt (wahrscheinlich im Hinblick auf Speicherzuweisungsoperationen - es gibt keine genauen Angaben dazu).
- Cgroup / systemd wurde in letzter Zeit stark überarbeitet, so dass der Upstream des Flusses impliziert, dass Linux-Distributoren darauf warten, dass sie sich zuerst niederlassen.
In CGroup v2 wird vermutet, dass memory.high
dies eine gute Option sein sollte, um die Speichernutzung durch eine Prozessgruppe zu drosseln und zu verwalten. Dieses Zitat legt jedoch nahe, dass die Überwachung des Gedächtnisdrucks mehr Arbeit erfordert (ab 2015).
Um zu bestimmen, ob eine Arbeitslast mehr Arbeitsspeicher benötigt, ist ein Maß für den Speicherdruck erforderlich - wie stark sich die Arbeitslast aufgrund von Speichermangel auswirkt. Leider ist der Mechanismus zur Überwachung des Speicherdrucks noch nicht implementiert.
Angesichts der Komplexität der systemd- und cgroup-Werkzeuge für den Benutzerraum gibt es keine einfache Möglichkeit, etwas angemessenes einzustellen und dieses Potenzial weiter auszubauen. Die cgroup- und systemd-Dokumentation für Ubuntu ist nicht so toll. Zukünftige Arbeit sollte für Desktop-Editionen von distro sein, um cgroups und systemd so einzusetzen, dass ssh und die X-Server- / Window-Manager-Komponenten bei hohem Speicherdruck Zugriff auf CPU, physischen Arbeitsspeicher und Speicher-IO mit höherer Priorität erhalten, um einen Wettbewerb mit den Prozessen zu vermeiden beschäftigt tauschen. Die CPU- und E / A-Prioritätsfunktionen des Kernels sind seit einiger Zeit verfügbar. Es scheint der vorrangige Zugriff auf physischen RAM zu sein, der fehlt.
Allerdings sind nicht einmal die CPU- und E / A-Prioritäten entsprechend eingestellt !? Als ich die systemd-Gruppenlimits, CPU-Freigaben usw. überprüft habe, hatte Ubuntu, soweit ich das beurteilen konnte, keine vordefinierten Prioritäten festgelegt. Ich lief zB:
systemctl show dev-mapper-Ubuntu\x2dswap.swap
Ich verglich das mit der gleichen Ausgabe für ssh, samba, gdm und nginx. Wichtige Dinge wie die grafische Benutzeroberfläche und die Remote-Administrationskonsole müssen bei allen Thrashing-Vorgängen gleichermaßen kämpfen.
Beispiel Speichergrenzen habe ich auf einem 16 GB RAM-System
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 kann das Thrashing nicht alle gemeinsam verhindern, aber ohne einen einzigen Prozess mit gieriger Speichernutzung oder einem Speicherverlust kann Thrashing verursacht werden. ZB habe ich gesehen, gnome-contacts
wie Speicher 8 GB + gesaugt werden, wenn weltliche Dinge wie das Aktualisieren der globalen Adressliste von einem Exchange-Server durchgeführt werden.
Wie man sieht ulimit -S -v
, haben viele Distributionen diesen harten und weichen Grenzwert als "unbegrenzt" festgelegt. Theoretisch könnte ein Prozess letztendlich viel Speicher anfordern, aber nur aktiv eine Teilmenge verwenden, wobei er denkt, dass ihm 24 GB RAM gegeben wurden Das System hat nur 16 GB. Das obige harte Limit führt dazu, dass Prozesse, die möglicherweise ordnungsgemäß ausgeführt wurden, abgebrochen werden, wenn der Kernel seine gierigen spekulativen Speicheranforderungen ablehnt.
Es fängt jedoch auch verrückte Dinge wie Gnome-Kontakte an, und anstatt meine Desktop-Reaktionsfähigkeit zu verlieren, erhalte ich die Fehlermeldung "nicht genügend freier Speicher":
Komplikationen für das Festlegen von ulimit für den Adressraum (virtueller Speicher)
Unglücklicherweise geben manche Entwickler vor, virtueller Speicher sei eine unendliche Ressource, und das Festlegen eines ulimit für virtuellen Speicher kann einige Apps beschädigen. ZB WebKit (von dem einige Gnome-Apps abhängig sind) fügte eine gigacage
Sicherheitsfunktion hinzu, die versucht, wahnsinnige Mengen an virtuellem Speicher zuzuordnen, und FATAL: Could not allocate gigacage memory
Fehler mit einem frechen Hinweis Make sure you have not set a virtual memory limit
passieren. Die ProblemumgehungGIGACAGE_ENABLED=no
verzichtet auf die Sicherheitsvorteile, aber auch die Einschränkung der Zuweisung von virtuellem Speicher bedeutet nicht, dass ein Sicherheitsmerkmal (z. B. eine Ressourcenkontrolle, die Denial-of-Service verhindern kann) fehlt. Ironischerweise scheinen sie zwischen Gigacage und Gnome-Entwicklern zu vergessen, dass die Begrenzung der Speicherzuordnung selbst eine Sicherheitssteuerung darstellt. Und leider bemerkte ich, dass die Gnome-Apps, die auf Gigacage angewiesen sind, nicht explizit ein höheres Limit fordern. In diesem Fall bricht sogar ein weiches Limit die Dinge.
Um ehrlich zu sein, wenn der Kernel es besser geschafft hat, die Speicherzuweisung auf der Grundlage der Verwendung des residenten Speichers anstelle des virtuellen Speichers zu verweigern, dann wäre das Vorgeben von virtuellem Speicher unbegrenzt weniger gefährlich.
Übererfüllung
Wenn Sie bevorzugen, dass Anwendungen den Speicherzugriff verweigern, und die Überbindung beenden möchten, verwenden Sie die folgenden Befehle, um zu testen, wie sich Ihr System bei hohem Speicherdruck verhält.
In meinem Fall war die Default-Commit-Ratio:
$ sysctl vm.overcommit_ratio vm.overcommit_ratio = 50
Dies wird jedoch nur dann wirksam, wenn Sie die Richtlinie ändern, um die Überlastung zu deaktivieren und das Verhältnis anzuwenden
sudo sysctl -w vm.overcommit_memory=2
Das Verhältnis implizierte, dass nur 24 GB Speicher insgesamt zugewiesen werden konnten (16 GB RAM * 0,5 + 16 GB SWAP). Ich würde also wahrscheinlich nie OOM auftauchen sehen und effektiv wäre es unwahrscheinlich, dass Prozesse ständig auf den Speicher im Swap zugreifen. Ich werde aber wahrscheinlich auch die Gesamtsystemeffizienz opfern.
Dies führt zum Absturz vieler Anwendungen, da Devs normalerweise nicht ordnungsgemäß mit dem Betriebssystem umgehen, das eine Speicherzuordnungsanforderung ablehnt. Das gelegentliche Risiko einer langwierigen Überbrückung aufgrund von Thrashing (all Ihre Arbeit nach einem Hard Reset) wird durch ein häufigeres Risiko des Absturzes verschiedener Apps ersetzt. In meinen Tests half es nicht viel, da der Desktop selbst abstürzte, als das System unter Speicherdruck stand und der Speicher nicht zugewiesen werden konnte. Zumindest Konsolen und SSH funktionierten trotzdem.
Wie funktioniert die VM-Überlastungsspeicherfunktion mehr Informationen?
Ich entschied mich dafür, zum Standard zurückzukehren sudo sysctl -w vm.overcommit_memory=0
, da der gesamte grafische Desktop-Stack und die darin enthaltenen Anwendungen trotzdem abstürzen.