Wie kann Swapoff so langsam sein?

77

Irgendwie habe ich zufällig 14 GB Speicher ausgelagert. Nachdem ich den Täter getötet habe, habe ich wieder jede Menge freien Speicherplatz, sodass ich dachte, ich könnte die wichtigen Daten wieder einspielen. Also mit 5 GB von 32 GB und 14 GB Swap-Speicherplatz lief ich swapoff -a... und 4 Stunden später war ungefähr die Hälfte der Arbeit beendet.

Das bedeutet weniger als 1 MB / s, während ich problemlos 200 MB / s kopieren kann. Mein Swap ist verschlüsselt, genauso wie alle normalen Partitionen. Mit aes-ni wird die CPU nicht merklich ausgelastet (und das Ausfüllen des Swap-Speicherplatzes dauerte nur wenige Minuten). Ich sehe, dass es keinen besonderen Grund gibt, zu optimieren swapoff, aber ich frage mich, wie es so langsam werden könnte.


Ich füge nur ein paar Daten hinzu: Mein Hauptspeicher ist 32 GB und ich habe 32 GB Swap-Speicherplatz auf jeder der 4 Festplatten (sicherlich ein Overkill, aber wen interessiert das?). Der gesamte Swap-Bereich kann in weniger als 5 Minuten entschlüsselt und gelesen werden:

time -p sudo sh -c 'for i in /dev/mapper/cryptswap?; do md5sum $i & done; wait'
014a2b7ef300e11094134785e1d882af  /dev/mapper/cryptswap1
a6d8ef09203c1d8d459109ff93b6627c  /dev/mapper/cryptswap4
05aff81f8d276ddf07cf26619726a405  /dev/mapper/cryptswap3
e7f606449327b9a016e88d46049c0c9a  /dev/mapper/cryptswap2
real 264.27

Das Lesen eines Teils einer Partition kann nicht langsamer sein als das Lesen aller Teile. Das Lesen von ungefähr 1/10 dauert jedoch ungefähr 100-mal länger.

Ich beobachtete, dass swapoffsowohl die CPU zum größten Teil im Leerlauf war (vielleicht 10% eines Kerns) als auch die Festplatten ("gemessen" durch die LEDs). Ich habe auch gesehen, dass die Swap-Räume nacheinander abgeschaltet wurden.

maaartinus
quelle
1
Ich frage mich, tritt das gleiche Phänomen auf, wenn das System ausgelagerte Seiten von selbst zurück in den RAM lädt. Wenn zum Beispiel ein System auf der Festplatte angehalten und dann gestartet wurde, wurde alles ausgelagert und in den Arbeitsspeicher zurückgeladen. Scheint mir auch sehr langsam zu sein.
Petr Pudlák
Sind alle Swap-Geräte mit der gleichen Priorität aktiviert?
Nils
@Petr Pudlák: Das Anhalten auf der Festplatte ist ein bisschen anders, es schreibt einfach den RAM-Inhalt in einen freien Bereich im Auslagerungsbereich, und dies (und Aufheben der Unterbrechung) ist wahrscheinlich viel schneller. Ich kann es nicht versuchen, da es mit verschlüsseltem Swap nicht funktioniert.
Maaartinus
@Nils: Ja, die Priorität ist dieselbe, ebenso wie die Festplatte und ihre Partitionierung.
Maaartinus
Das macht es merkwürdiger. In diesem Fall wird der Swap über alle Festplatten verteilt - dies sollte sehr schnell gehen. Haben Sie iostat -d 5während swapoffauch Low IO auf den Datenträgern angezeigt?
Nils

Antworten:

53

Schauen wir uns zunächst an, was Sie von Ihrer Festplatte erwarten können. Ihre Festplatte kann nacheinander 200 MB / s verarbeiten . Wenn Sie Suchzeiten berücksichtigen, kann dies viel langsamer sein. Um ein beliebiges Beispiel auszuwählen, werfen Sie einen Blick auf die technischen Daten einer der modernen 3-TB-Festplatten von Seagate, der ST3000DM001 :

  • Max. Dauerhafte Datenrate: 210 MB / s

  • Suchdurchschnittslesung: <8,5 ms

  • Bytes pro Sektor: 4.096

Wenn Sie nie suchen müssen und sich Ihr Swap in der Nähe des Randes der Festplatte befindet, können Sie mit einer maximalen Rate von 210 MB / s rechnen

Wenn Ihre Swap-Daten jedoch vollständig fragmentiert sind, müssen Sie im schlimmsten Fall nach jedem Sektor suchen, den Sie lesen. Das bedeutet, dass Sie nur alle 8,5 ms 4 KB lesen können, oder 4 KB / 0,0085 = 470 KB / s

Auf Anhieb ist es also nicht unvorstellbar, dass Sie tatsächlich mit Festplattengeschwindigkeiten konfrontiert werden.


Das heißt, es scheint albern, dass swapoffes so langsam laufen würde und Seiten in der falschen Reihenfolge gelesen werden müssten, besonders wenn sie schnell geschrieben würden (was eine falsche Reihenfolge impliziert). Aber vielleicht funktioniert der Kernel so. Ubuntu-Fehlerbericht # 486666 behandelt das gleiche Problem:

The swap is being removed at speed of 0.5 MB/s, while the
hard drive speed is 60 MB/s;
No other programs are using harddrive a lot, system is not under
high load etc.

Ubuntu 9.10 on quad core.

Swap partition is encrypted.
Top (atop) shows near 100% hard drive usage
  DSK | sdc | busy 88% | read 56 | write 0 | avio 9 ms |
but the device transfer is low (kdesysguard)
  0.4 MiB/s on /dev/sdc reads, and 0 on writes

Eine der Antworten war:

It takes a long time to sort out because it has to rearrange and flush the
memory, as well as go through multiple decrypt cycles, etc. This is quite
normal

Der Fehlerbericht wurde ungelöst geschlossen.

Mel Gormans Buch " Den Linux Virtual Memory Manager verstehen " ist etwas veraltet, stimmt jedoch zu, dass dies ein langsamer Vorgang ist:

Die für die Deaktivierung eines Bereichs verantwortliche Funktion wird vorhersehbarerweise aufgerufen sys_swapoff(). Diese Funktion beschäftigt sich hauptsächlich mit der Aktualisierung der swap_info_struct. Die Hauptaufgabe des Seitenwechsels auf jeder ausgelagerten Seite ist die Verantwortung, try_to_unuse()die extrem teuer ist.

Auf der Mailing-Liste für den Linux-Kernel wird ab 2007 etwas mehr darüber diskutiert, was unter dem Thema " Beschleunigung des Swapoffs " zu verstehen ist - obwohl die dort diskutierten Geschwindigkeiten etwas höher sind als die, die Sie sehen.


Es ist eine interessante Frage, die wahrscheinlich im Allgemeinen ignoriert wird, da sie swapoffselten verwendet wird. Ich glaube, wenn Sie es wirklich wollen , ausfindig zu machen , ist der erste Schritt der Festplatte Nutzungsmuster mehr würde versuchen , vorsichtig (mit vielleicht zu beobachten atop, iostatoder noch leistungsfähigere Werkzeugen wie perfoder systemtap). Dinge, nach denen gesucht werden muss, sind möglicherweise übermäßiges Suchen, kleine E / A-Vorgänge, ständiges Umschreiben und Verschieben von Daten usw.

Jim Paris
quelle
5
Hervorragende Erklärung. Es sollte beachtet werden, dass es möglich ist, den größten Teil der Fragmentierung zu umgehen und einen Großteil des Swaps schnell freizugeben,
Brandon DuPree
Es ist nicht nur Fragmentierung / Suchzeit. Mein Swap ist auf SSD und zufällige Lesevorgänge sind sehr schnell, aber der Swapoff-Befehl ist viel langsamer als er sollte und meine SSD-Last liegt bei etwa 1% Auslastung. Ich vermute, dass es irgendwo im Kernel oder beim Swapoff zu List-Walking kommt (der ~ 90-100% CPU verbraucht). Wenn alle Arbeiten der Reihe nach ausgeführt werden und die Suchvorgänge auf der Festplatte ebenfalls langsam sind, kann sich dies natürlich erheblich summieren.
Thomas Guyot-Sionnest
33

Ich habe das gleiche Problem mit meinem Laptop gehabt, der eine SSD hat, also sollte das Suchen mal kein Problem sein.

Ich habe eine alternative Erklärung gefunden . Hier ist ein Auszug

So wie es jetzt funktioniert, überprüft swapoff jede ausgelagerte Speicherseite in der Swap-Partition und versucht, alle Programme zu finden, die sie verwenden. Wenn sie nicht sofort gefunden werden können, werden die Seitentabellen aller ausgeführten Programme durchsucht, um sie zu finden. Im schlimmsten Fall werden alle Seitentabellen für jede ausgelagerte Seite in der Partition überprüft. Das ist richtig - die gleichen Seitentabellen werden immer wieder überprüft.

Es ist also eher ein Kernelproblem als irgendetwas anderes.

Nick Craig-Wood
quelle
Nein, es ist IMHO kein Kernel-Problem. So swapoffwird es umgesetzt. Wenn der ausgelagerte Prozess beendet wird, dauert es nicht so lange.
Marki555,
15
Es ist ein Problem mit der Implementierung von Swapoff, das sich im Kernel befindet - daher ein Kernelproblem! Sie können sehen, ob Sie strace swapoffso ziemlich alles, was es tut, den swapoffSystemaufruf aufrufen.
Nick Craig-Wood
1
Ich habe einen Server mit 48 GB RAM (32 Kerne), hatte 6 GB freien Bug Swap verwendet 0,7 GB. swappiness = 10, versuchte es mit 0 und versuchte es auch mit dem Swapoff, um zu sehen, was passiert. Das Auswechseln dauert eine Ewigkeit, wahrscheinlich 30 Minuten, und das Auswechseln ist extrem langsam. Ich habe SSD unter fast keiner Last und CPU ist ähnlich, erwarten Sie den Auslagerungsprozess, der eine CPU 100% nimmt.
Sorin
1
Es ist das Problem, wie Swapoff implementiert ist (im Kernel). Es gab vor ein paar Jahren Diskussionen über einen viel besseren Ansatz in Kernel-Dev, aber sie sagen, dass dies ein Eckfall ist und nicht die Anstrengung will, ihn zu ändern.
Marki555,
7
Auf Servern mit 1 TB RAM (ja, TB) und 2 GB Swap (alberne SAP-Anforderung) dauerte der Swap-Vorgang 12 Stunden, um 5% dieser 2 GB freizugeben (mit 1 CPU-Kern bei 100%).
Marki555,
22

Ja, der swapoffMechanismus ist entsetzlich ineffizient. Die Problemumgehung ist einfach: Iterieren Sie über Prozesse, anstatt über die ausgetauschten Seiten zu iterieren. Verwenden Sie dieses Python-Skript (ich bin nicht verbunden):

git clone https://github.com/wiedemannc/deswappify-auto

Beachten Sie, dass der Daemon-Betriebsmodus nur für Desktops / Laptops gilt, die häufig in den Ruhezustand versetzt werden. Ich würde es nicht als Daemon auf einem Serversystem ausführen - starte es einfach im Vordergrund, warte, bis es meldet, dass es sich um einige Prozesse gekümmert hat, dann stoppe es und versuche:

swapoff /dev/x

Da die meisten Seiten jetzt sowohl im Swap als auch im Memory vorhanden sind, swapoffhat das sehr wenig zu tun und sollte jetzt rasant schnell sein (ich habe Hunderte von MB / s gesehen).

Geschichte Abschnitt voraus

Das oben erwähnte Python-Skript basiert auf dem Rest dieser Antwort, was wiederum meine Verbesserung dieser älteren Antwort war, die von jlong verfasst wurde . Da das Skript viel sicherer ist, empfehle ich, nur den Rest meiner Antwort als letzte Verteidigungslinie zu versuchen :

perl -we 'for(`ps -e -o pid,args`) { if(m/^ *(\d+) *(.{0,40})/) { $pid=$1; $desc=$2; if(open F, "/proc/$pid/smaps") { while(<F>) { if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ $start_adr=$1; $end_adr=$2; }  elsif(m/^Swap:\s*(\d\d+) *kB/s){ print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" }}}}}' | sort -Vr | head

Dies läuft vielleicht 2 Sekunden und wird nicht wirklich etwas tun, listen nur die Top 10 der Speichersegmente (tatsächlich druckt mehr Einzeiler, ja , ich tun Einzeiler lieben, nur die Befehle prüfen, akzeptieren das Risiko, Kopieren und Einfügen in Ihre Muschel; diese wird tatsächlich aus Swap lesen).

...Paste the generated one-liners...
swapoff /your/swap    # much faster now

Der Haupt-Einzeiler ist (für mich) sicher, außer er liest viel / proc.

Die für Ihre manuelle Prüfung vorbereiteten Unterbefehle sind nicht sicher . Jeder Befehl hängt einen Prozess für die Dauer des Lesens eines Speichersegments aus dem Swap. Daher ist es bei Prozessen, die keine Pausen tolerieren, unsicher. Die Übertragungsgeschwindigkeiten, die ich sah, lagen in der Größenordnung von 1 Gigabyte pro Minute. (Das oben erwähnte Python-Skript hat diesen Mangel behoben).

Eine andere Gefahr besteht darin, dass das System zu stark belastet wird. Überprüfen Sie dies mit den üblichen Methoden free -m

Was tut es?

for(`ps -e -o pid,args`) {

  if(m/^ *(\d+) *(.{0,40})/) { 
    $pid=$1; 
    $desc=$2; 

    if(open F, "/proc/$pid/smaps") { 

      while(<F>) { 

        if(m/^([0-9a-f]+)-([0-9a-f]+) /si){ 
          $start_adr=$1; 
          $end_adr=$2; 
        } elsif( m/^Swap:\s*(\d\d+) *kB/s ){
          print "SSIZE=$1_kB\t gdb --batch --pid $pid -ex \"dump memory /dev/null 0x$start_adr 0x$end_adr\"\t2>&1 >/dev/null |grep -v debug\t### $desc \n" 
        }
      }
    }
  }
}

Die Ausgabe dieses Perl-Skripts ist eine Reihe von gdbBefehlen, dump memory (range)die ausgelagerte Seiten in den Speicher zurückrufen.

Die Ausgabe beginnt mit der Größe, daher ist es einfach genug, sie | sort -Vr | headzu durchlaufen, um die 10 größten Segmente nach Größe (SSIZE) zu erhalten. Das -Vsteht für versionsnummerngerechte Sortierung, funktioniert aber für meinen Zweck. Ich konnte nicht herausfinden, wie die numerische Sortierung funktioniert.

kubanczyk
quelle
Sie würden hier die numerische Sortierung verwenden mitsort -t = -k 2n
Stéphane Chazelas
9
Es scheint keine Notwendigkeit zu geben, gdb zu verwenden, um den Prozessspeicher zu überprüfen (zumindest bei neueren Kerneln). Man kann einfach direkt öffnen /proc/$pid/mem, suchen und lesen. Der PoC basiert größtenteils auf Ihrem Snippet: gist.github.com/WGH-/91260f6d65db88be2c847053c49be5ae Auf diese Weise wird der Prozess nicht gestoppt, AFAIK, es sollten keine Gefahren entstehen.
WGH
10

Wenn während des Auslagerungsvorgangs ein in Verwendung befindlicher Auslagerungsschlitz erkannt wird, wird der Kernel zuerst auf der Seite ausgetauscht. Die Funktion unuse_process () versucht dann, alle Seitentabelleneinträge zu finden, die der gerade ausgelagerten Seite entsprechen, und führt die erforderlichen Aktualisierungen der Seitentabellen durch. Die Suche ist erschöpfend und sehr zeitaufwendig: Sie durchsucht jeden Speicherdeskriptor (des gesamten Systems) und überprüft seine Seitentabelleneinträge nacheinander.

Weitere Informationen finden Sie auf Seite 724 unter "Grundlegendes zum Linux-Kernel 3. Version".

Leslie
quelle