Wenn sich mein Linux-System dem Paging nähert (in meinem Fall 16 GB RAM fast voll, 16 GB Swap vollständig leer), wird das System durch einen neuen Prozess X beim Versuch, Speicher zuzuweisen, vollständig gesperrt. Das heißt, bis eine unverhältnismäßig große Anzahl von Seiten (bezogen auf die Gesamtgröße und Rate der Speicherzuweisungsanforderungen von X) ausgelagert wurde. Beachten Sie, dass nicht nur die Benutzeroberfläche nicht mehr reagiert, sondern auch grundlegende Dienste wie sshd vollständig blockiert werden.
Dies sind zwei Code-Teile (zugegebenermaßen grob), die ich verwende, um dieses Verhalten auf "wissenschaftlichere" Weise auszulösen. Der erste erhält zwei Zahlen x, y von der Befehlszeile und beginnt mit der Zuweisung und Initialisierung mehrerer Teile von y Bytes, bis mehr als x Gesamtbytes zugewiesen wurden. Und schläft dann einfach auf unbestimmte Zeit. Dies wird verwendet, um das System an den Rand des Paging zu bringen.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv) {
long int max = -1;
int mb = 0;
long int size = 0;
long int total = 0;
char* buffer;
if(argc > 1)
{
max = atol(argv[1]);
size = atol(argv[2]);
}
printf("Max: %lu bytes\n", max);
while((buffer=malloc(size)) != NULL && total < max) {
memset(buffer, 0, size);
mb++;
total=mb*size;
printf("Allocated %lu bytes\n", total);
}
sleep(3000000);
return 0;
}
Der zweite Teil des Codes macht genau das, was der erste tut, mit der Ausnahme, dass er sleep(1);
direkt nach dem steht printf
(ich werde nicht den gesamten Code wiederholen). Diese Option wird verwendet, wenn das System kurz vor dem Auslagern steht, um das Auslagern von Seiten auf "sanfte" Weise zu ermöglichen, dh indem langsam die Zuweisung neuer Speicherbereiche angefordert wird (sodass das System auf jeden Fall Seiten auslagern kann und halten Sie sich mit den neuen Anfragen auf dem Laufenden).
Nennen wir also mit den beiden kompilierten Code-Teilen die jeweiligen exes fasteater und sloweater:
1) starte deine Lieblings-GUI (natürlich nicht unbedingt erforderlich)
2) starte ein Mem / Swap Meter (zB watch -n 1 free
)
3) Starten Sie mehrere Instanzen von fasteater x y
x in der Größenordnung von Gigabyte und y in der Größenordnung von Megabyte. Tun Sie es, bis Sie fast den Widder gefüllt haben.
4) Starten Sie erneut eine Instanz von sloweater x y
, wobei x in der Größenordnung von Gigabyte und y in der Größenordnung von Megabyte liegt.
Nach Schritt 4) sollte (und das passiert bei meinem System immer) passieren, dass das System unmittelbar nach dem Entleeren des Stempels vollständig verriegelt wird. gui ist gesperrt sshd ist gesperrt usw. ABER nicht für immer! Nachdem sloweater seine Zuweisungsanforderungen beendet hat, wird das System in der folgenden Situation wieder zum Leben erweckt (nach Minuten des Sperrens, nicht nach Sekunden ...):
a) RAM ist ungefähr voll
b) Swap ist auch ungefähr voll (denken Sie daran, es war am Anfang leer)
c) Keine Mörderintervention.
Beachten Sie, dass sich die Swap-Partition auf einer SSD befindet. Das System scheint also nicht in der Lage zu sein, Seiten schrittweise vom RAM zum Swap zu verschieben (vermutlich von den Fasteatern, die gerade schlafen), um Platz für die langsamen (und nur wenige Megabyte großen) Anforderungen des Sloweaters zu schaffen.
Jetzt korrigiert mich jemand, wenn ich falsch liege, aber dies scheint nicht so zu sein, wie sich ein modernes System in dieser Umgebung verhalten sollte. Es scheint sich wie die alten Systeme zu verhalten (waaaaay back), als es keine Unterstützung für Paging gab und das virtuelle Speichersystem nur den gesamten Speicherplatz eines Prozesses anstelle weniger Seiten ausgelagert hat.
Kann das auch jemand testen? Und vielleicht jemand, der auch ein BSD-System hat.
UPDATE 1
Ich folgte den Ratschlägen von Mark Plotnick in den Kommentaren und begann, vmstat 1 >out
bevor ich mit dem Paging-Test fortfuhr. Sie können das Ergebnis unten sehen (ich schneide den gesamten Anfangsteil, in dem der Stößel gefüllt ist, ohne dass ein Austausch erforderlich ist):
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 6144 160792 8 272868 0 0 0 0 281 1839 1 0 99 0 0
0 0 6144 177844 8 246096 0 0 0 0 425 2300 1 1 99 0 0
0 0 6144 168528 8 246112 0 0 16 0 293 1939 1 0 99 0 0
0 0 6144 158320 8 246116 0 0 0 0 261 1245 0 0 100 0 0
2 0 10752 161624 8 229024 0 4820 17148 4820 845 3656 1 2 97 0 0
2 0 10752 157300 8 228096 0 0 88348 0 2114 8902 0 5 94 1 0
0 0 10752 176108 8 200052 0 0 108312 0 2466 9772 1 5 91 3 0
0 0 10752 170040 8 196780 0 0 17380 0 507 1895 0 1 99 0 0
0 10 10752 160436 8 191244 0 0 346872 20 4184 17274 1 9 64 26 0
0 29 12033856 152888 8 116696 5992 15916880 1074132 15925816 819374 2473643 0 94 0 6 0
3 21 12031552 295644 8 136536 1188 0 11348 0 1362 3913 0 1 10 89 0
0 11 12030528 394072 8 151000 2016 0 17304 0 907 2867 0 1 13 86 0
0 11 12030016 485252 8 158528 708 0 7472 0 566 1680 0 1 23 77 0
0 11 12029248 605820 8 159608 900 0 2024 0 371 1289 0 0 31 69 0
0 11 12028992 725344 8 160472 1076 0 1204 0 387 1381 0 1 33 66 0
0 12 12028480 842276 8 162056 724 0 3112 0 357 1142 0 1 38 61 0
0 13 12027968 937828 8 162652 776 0 1312 0 363 1191 0 1 31 68 0
0 9 12027456 1085672 8 163260 656 0 1520 0 439 1497 0 0 30 69 0
0 10 12027200 1207624 8 163684 728 0 992 0 411 1268 0 0 42 58 0
0 9 12026688 1331492 8 164740 600 0 1732 0 392 1203 0 0 36 64 0
0 9 12026432 1458312 8 166020 628 0 1644 0 366 1176 0 0 33 66 0
Wie Sie sehen, gibt es, sobald der Swap involviert ist, einen massiven Swapout von 15916880 KByte auf einmal, der, glaube ich, für die gesamte Dauer des Einfrierens des Systems anhält. Und all dies wird anscheinend durch einen Prozess (den Sloweater) verursacht, der nur 10 MB pro Sekunde benötigt.
UPDATE 2: Ich habe eine schnelle Installation von FreeBSD durchgeführt und das gleiche Zuweisungsschema wie unter Linux wiederholt ... und es war so reibungslos, wie es sein sollte. FreeBSD tauschte die Seiten nach und nach aus, während der Sloweater alle 10-MB-Speicherbereiche zuordnete. Keine einzige Störung ... WTF geht hier vor ?!
UPDATE 3: Ich habe einen Fehler beim Kernel-Bugtracker gemeldet. Es scheint etwas Aufmerksamkeit zu bekommen, also ... Daumen drücken ...
vmstat 1>somefile
direkt vom System aus starten und dann sehen, was es meldet, nachdem das System wieder zum Leben erweckt wurde. Ich werde das versuchen.
swappiness
ist die Standardeinstellung 60 (nicht das Ändern ergibt ein besseres Ergebnis). Der mit dem vmstat
Lauf verwendete Kernel ist 4.14.35, aber ich habe 4.15, 4.16 ausprobiert und bin sogar auf die 4.0-Serie (!) Zurückgekehrt: immer das gleiche Verhalten. Und es ist nicht so, dass ich eine seltsame Distribution verwende, es ist nur Debian. Ich verwende nicht die Kernel-Images von Debian (nicht meine, die ungewöhnliche Konfigurationen haben), aber ich habe eines davon ausprobiert ... dasselbe Verhalten.