Warum stottert mein Linux-System, wenn ich nicht ständig Caches lösche?

525
Pneumaticat

In den letzten Monaten hatte ich ein äußerst irritierendes Problem mit meinem Linux-System: Es stottert bei der Audiowiedergabe von Firefox, der Mausbewegung usw., wobei alle paar Sekunden ein winziges (aber immer noch spürbares) Stottern von Sub-Sekunden auftritt. Das Problem verschlechtert sich, wenn der Speichercache gefüllt wird oder wenn sehr platten- / speicherintensive Programme ausgeführt werden (z restic. B. Sicherungssoftware ). Wenn der Cache jedoch nicht voll ist (z. B. unter sehr geringer Last), läuft alles sehr reibungslos.

Wenn perf topich durch die Ausgabe schaue, sehe ich, dass list_lru_count_onewährend dieser Verzögerungszeiten ein hoher Aufwand (~ 20%) vorliegt. htopzeigt auch die kswapd0Verwendung von 50-90% CPU (obwohl es den Eindruck hat, dass die Auswirkungen viel größer sind). In Zeiten extremer Verzögerung wird der htopCPU-Zähler häufig von der CPU-Auslastung des Kernels dominiert.

Die einzige Problemumgehung, die ich gefunden habe, besteht entweder darin, den Kernel dazu zu zwingen, freien Speicher ( sysctl -w vm.min_free_kbytes=1024000) zu behalten ( ), oder Speichercaches ständig durchzulassen echo 3 > /proc/sys/vm/drop_caches. Keines ist natürlich ideal und löst auch das Stottern nicht vollständig; es macht es nur weniger häufig.

Hat jemand eine Idee, warum dies geschehen könnte?

Systeminformationen

  • i7-4820k mit 20 GB (nicht übereinstimmendem) DDR3-RAM
  • Wiedergabe unter Linux 4.14-4.18 unter NixOS instabil
  • Führt Docker-Container und Kubernetes im Hintergrund aus (was meiner Meinung nach nicht zu Mikroschneiden führen sollte)

Was ich schon probiert habe

  • Ändern von E / A-Schedulern (bfq) mithilfe von E / A-Schedulern mit mehreren Werten
  • Das -ckPatchset von Con Kolivas verwenden (hat nicht geholfen)
  • Swap deaktivieren, Swappiness ändern, Zram verwenden

BEARBEITEN : Zur Verdeutlichung ein Bild von htopund perfwährend einer solchen Verzögerungsspitze. Beachten Sie die hohe list_lru_count_oneCPU-Last und die kswapd0+ hohe Kernel-CPU-Auslastung.

Top und Perfekte Ausgabe

2
Stimmen Sie die cpu / io-Nutzung mit cgroup ab. Geben Sie interaktiven Aufgaben mehr Priorität. Ipor Sircer vor 5 Jahren 0
Ich erlebe das gleiche auf meinem System (keine Container). Ich vermute einen Fehler, der die Caches zusammenbricht, aber ich weiß es nicht. Ich würde mich sehr für eine Antwort interessieren. Ich habe auch versucht, die I / O-Scheduler zu ändern, half nicht. Das System pausiert, selbst wenn es nur wenig geladen ist, so dass die Priorität bei interaktiven Aufgaben definitiv nicht helfen wird. dirkt vor 5 Jahren 0
Kommt das gleiche vor, wenn nur ein Ram-Stick verwendet wird? Sie erwähnen, dass dies auch bei geringer Belastung der Fall ist. Möglicherweise gibt es ein subtiles Timing / elektrisches Problem in den verschiedenen RAMs Christopher Hostage vor 5 Jahren 0
@ChristopherHostage Ich habe es heute gerade mit 2/4 RAM-Sticks ausprobiert, und das Stottern war immer noch vorhanden. Pneumaticat vor 5 Jahren 0
@IporSircer Ich glaube nicht, dass es sich bei der CPU-Priorisierung um ein Problem handelt. Die Stottern stimmen mit der hohen * Kernel * - CPU - Auslastung überein, nicht mit der Verwendung durch andere Programme. Korrigieren Sie mich, wenn ich falsch liege. Pneumaticat vor 5 Jahren 0

2 Antworten auf die Frage

2
Austin Hemmelgarn

Es hört sich an, als hätten Sie schon viele der Dinge ausprobiert, die ich zuerst vorgeschlagen hätte (Swap-Konfiguration anpassen, E / A-Scheduler ändern usw.).

Abgesehen von dem, was Sie bereits versucht haben zu ändern, würde ich vorschlagen, die etwas hirnroten Voreinstellungen für das VM-Rückschreibeverhalten zu ändern. Dies wird durch die folgenden sechs sysctl-Werte verwaltet:

  • vm.dirty_ratio: Steuert, wie viel Schreibvorgänge für das Zurückschreiben anstehen müssen, bevor es ausgelöst wird. Behandelt Vordergrundrückschreiben (pro Prozess) und wird als ganzzahliger Prozentsatz des Arbeitsspeichers ausgedrückt. Der Standardwert ist 10% des Arbeitsspeichers
  • vm.dirty_background_ratio: Steuert, wie viel Schreibvorgänge für das Zurückschreiben anstehen müssen, bevor es ausgelöst wird. Verarbeitet Hintergrundrückschreiben (systemweit) und wird als ganzzahliger Prozentsatz des Arbeitsspeichers ausgedrückt. Der Standardwert ist 20% des RAM
  • vm.dirty_bytes: Gleich wie vm.dirty_ratio, außer ausgedrückt als Gesamtanzahl von Bytes. Entweder dies oder vm.dirty_ratio wird verwendet, je nachdem, was als letztes geschrieben wurde.
  • vm.dirty_background_bytes: Gleich wie vm.dirty_background_ratio, außer ausgedrückt als Gesamtanzahl von Bytes. Entweder dies oder vm.dirty_background_ratio wird verwendet, je nachdem, was als letztes geschrieben wurde.
  • vm.dirty_expire_centisecs: Wie viele Hundertstelsekunden müssen vergehen, bevor das ausstehende Rückschreiben beginnt, wenn die obigen vier sysctl-Werte dies nicht bereits auslösen würden. Standardeinstellung ist 100 (eine Sekunde).
  • vm.dirty_writeback_centisecs: Wie oft (in Hundertstelsekunden) wird der Kernel schmutzige Seiten für das Zurückschreiben auswerten. Standardeinstellung ist 10 (eine Zehntelsekunde).

Mit den Standardwerten führt der Kernel jede Zehntelsekunde Folgendes aus:

  • Schreiben Sie alle geänderten Seiten in den permanenten Speicher, wenn sie vor mehr als einer Sekunde zuletzt geändert wurden.
  • Schreiben Sie alle modifizierten Seiten für einen Prozess aus, wenn die Gesamtmenge des nicht ausgeschriebenen Arbeitsspeichers 10% des Arbeitsspeichers überschreitet.
  • Schreiben Sie alle modifizierten Seiten im System aus, wenn die Gesamtmenge des nicht ausgeschriebenen Speichers 20% des Arbeitsspeichers überschreitet.

Es sollte also leicht zu erkennen sein, warum die Standardwerte Probleme für Sie verursachen können, da Ihr System möglicherweise versucht, jede Zehntelsekunde bis zu 4 Gigabyte Daten in den permanenten Speicher zu schreiben .

Der allgemeine Konsens besteht heutzutage darin, sich vm.dirty_ratioauf 1% des RAM und vm.dirty_background_ratio2% einzustellen, was für Systeme mit weniger als 64 GB RAM zu einem Verhalten führt, das dem ursprünglich beabsichtigten entspricht.

Einige andere Dinge zu untersuchen:

  • Erhöhen Sie das vm.vfs_cache_pressureSysctl etwas. Dies steuert, wie aggressiv der Kernel Speicher aus dem Cache des Dateisystems beansprucht, wenn er RAM benötigt. Der Standardwert ist 100, es nicht unter 50 bis etwas niedriger (Du wirst wirklich schlechtes Verhalten, wenn man unter 50 gehen, einschließlich OOM Bedingungen) und erhöht es nicht viel mehr als etwa 200 (viel höher und die Der Kernel verschwendet Zeit damit, den Speicher zurückzugewinnen. Ich habe festgestellt, dass das Anheben von bis zu 150 tatsächlich die Reaktionsfähigkeit deutlich verbessert, wenn Sie über einen relativ schnellen Speicher verfügen.
  • Ändern Sie den Speicherüberlastungsmodus. Dies kann durch Ändern des Werts von vm.overcommit_memorysysctl erfolgen. Standardmäßig verwendet der Kernel einen heuristischen Ansatz, um zu versuchen, vorherzusagen, wie viel RAM er tatsächlich leisten kann. Wenn Sie diesen Wert auf 1 setzen, wird die Heuristik deaktiviert und der Kernel wird aufgefordert, sich so zu verhalten, als hätte er unendlichen Speicher. Wenn Sie diesen Wert auf 2 setzen, wird der Kernel angewiesen, nicht mehr Speicherplatz als die Gesamtmenge des Swap-Speichers im System zuzüglich eines Prozentsatzes des tatsächlichen Arbeitsspeichers (gesteuert von vm.overcommit_ratio) festzulegen .
  • Versuchen Sie, das vm.page-clusterSysctl zu optimieren. Hiermit wird gesteuert, wie viele Seiten gleichzeitig ein- oder ausgeblendet werden (dies ist ein logarithmischer Wert der Basis-2, dh der Standardwert von 3 wird auf 8 Seiten übersetzt). Wenn Sie tatsächlich tauschen, kann dies dazu beitragen, die Leistung beim Ein- und Auslagern von Seiten zu verbessern.
Danke für die ausführlichen Vorschläge! Leider arbeitet keiner von ihnen für mich. Ich habe versucht, das Dirty-Verhältnis, den VFS-Cache-Druck und das Seiten-Cluster ohne Wirkung zu ändern. vm.overcommit_memory = 1 hatte keine Änderung, und = 2 führte im Grunde zum Absturz meines Systems, daher ist das auch kein Thema. Pneumaticat vor 5 Jahren 0
Haben Sie KSM oder THP aktiviert? Wenn ja, würde ich vorschlagen, sie zu deaktivieren und zu sehen, ob das überhaupt hilft. Austin Hemmelgarn vor 5 Jahren 0
Nein, keiner ist aktiviert. THP ist durch "transparent_hugepage = never" tatsächlich explizit deaktiviert, aber ich habe versucht, es wieder zu aktivieren, und es hat keinen Unterschied gemacht. Pneumaticat vor 5 Jahren 0
0
Pneumaticat

Das Problem wurde gefunden!

Es stellt sich heraus, dass dies ein Leistungsproblem im Arbeitsspeicherausfall von Linux ist, wenn viele Container / Speichergruppen vorhanden sind. (Haftungsausschluss: Meine Erklärung ist möglicherweise fehlerhaft, ich bin kein Kernel-Entwickler.) Das Problem wurde in 4.19-rc1 + in diesem Patch-Set behoben :

Dieses Patcheset löst das Problem mit dem langsamen shrink_slab (), das auf Maschinen mit vielen Schrumpfern und Speichergruppen (dh mit vielen Containern) auftritt. Das Problem ist die Komplexität von shrink_slab () ist O (n ^ 2) und es wächst mit dem Wachstum der Containerzahlen zu schnell.

Lassen Sie uns 200 Container haben, und jeder Container hat 10 Mounts und 10 Cgroups. Alle Containeraufgaben sind isoliert und berühren keine Fremdcontainerhalterungen.

Im Falle einer globalen Rückforderung muss eine Aufgabe alle Memcgs durchlaufen und alle Memcg-fähigen Verkleinerer für alle aufrufen. Das bedeutet, die Task muss für jedes Memcg 200 * 10 = 2000-Verkleinerer besuchen. Da es 2000 Memcgs gibt, sind die Aufrufe von do_shrink_slab () 2000 * 2000 = 4000000.

Mein System wurde besonders hart getroffen, da ich eine große Anzahl von Containern betrieb, was wahrscheinlich dazu führte, dass das Problem auftrat.

Meine Schritte zur Fehlerbehebung, falls sie für alle hilfreich sind, bei denen ähnliche Probleme auftreten:

  1. Beachten Sie die kswapd0Verwendung einer Tonne CPU, wenn mein Computer stottert
  2. Versuchen Sie, die Docker-Container anzuhalten und den Speicher erneut zu füllen. Der Computer ruckelt nicht!
  3. Run ftrace( in Anlehnung an Julia Evans großartige Erklärung Blog ) eine Spur zu bekommen, sehen, dass die kswapd0Tendenz in stecken zu bleiben shrink_slab, super_cache_countund list_lru_count_one.
  4. Google shrink_slab lru slow, finde das Patchset!
  5. Wechseln Sie zu Linux 4.19-rc3 und überprüfen Sie, ob das Problem behoben ist.