Was bedeutet eigentlich IO Wait wirklich?

Ich hatte heute einen Kunden bei dem der  IO-Wait sehr hoch war. Das hat mich neugierig gemacht… was ist eigentlich IO-Wait in Linux wirklich?

Zuerstmal zur Ausgabe von vmstat:

procs -----------memory---------- ---swap-- -----io---- -system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  8 107296 197648 429476 17143372    0    0  1097   282    7   10  8  2 73 18  0
 0  7 107296 197648 429476 17143388    0    0     0   552  215  287  0  0  0 100  0
 0  8 107296 197756 429480 17143400    0    0     0   492  117  173  0  0 19 81  0
 0  8 107296 197756 429484 17143352    0    0     0   312  153  231  0  0 16 84  0
 0  7 107296 197756 429484 17143372    0    0     0   368  161  250  0  0  0 100  0
 0  7 107296 197756 429484 17143376    0    0     0   496  501  725  2  1  6 92  0

Was sagt und das nun über das System welches wir gerade untersuchen?
Die erste Zeile enthält die Durchschnittswerte seit dem letzen Reboot. Diese ignorieren wir einfach mal geflissentlich, denn da ist natürlich auch die Nacht mit drin und in der Nacht arbeitet der Kunde nicht.
Die nächste Zeile lautet nun also so:

procs -----------memory---------- ---swap-- -----io---- -system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  7 107296 197648 429476 17143388    0    0     0   552  215  287  0  0  0 100  0

Wir haben hier 0 running processes (da bedeutet entweder sie sind blockiert oder aber das System ist am nichtstun) und 7 blockierte Prozesse (aha – 7 Prozesse würden gerne arbeiten, können aber nicht!).
Die nächsten Werte zeigen uns das das System etwas Swap verwendet (solange das nicht mehr oder weniger wird ist das unkritisch!) dass noch etwas Memory Free ist, und dass viel Buffer/Cache verwendet wird.
Die Werte für si (Swap in) und so (Swap out) sind 0, und das ist auch gut so.
Die Werte fürs IO-System bi (brought in) und bo (brought out) zeigen uns dass momentan auf die Platten geschrieben wird. Das Filesystem hat 4k Blöcke („stat -f /database“) und somit würden hier ca. 2 MB/sec geschrieben. Das erscheint mir ziemlich wenig.
Die nächsten Werte zeigen Aktivität auf dem System. 215 Interrupts und 287 Context Switches. Ob das nun viel oder wenig für 7 blockierte Prozesse ist müsste man wohl von System zu System bewerten.
Weiter gehts mit 0% CPU im Usermode, 0% CPU im Systemmode und 0% CPU im Idlemode.
Es folgen 100% CPU im IOWait und 0% Steal.

Jetzt ist es die Spalte IOWait die mich stutzig gemacht hat.
Diesen Werte gibt es so in anderen Tools die die Prozessorauslatung anzeigen (htop, top) auch. Nur was bedeutet er?

Kurz zum Verständnis warum mich das so verwirrt:
Eine CPU kann nicht nichtstun. Das geht einfach nicht. (Mal abgesehen von verschiedenen Sleep-Modes – die wir hier mal außer Acht lassen).
Eine CPU lässt IMMER Programmcode laufen. Einmal gestartet muss Sie endlos Instruktionen fetchen und ausführen. Heißt also: Auf die Festplatte warten geht gar nicht!

CPUs befinden sich eigentlich immer in drei Zuständen:
1. Sie lassen Programmcode im Usermode laufen – also normale Programme.
2. Sie lassen Programmcode im Systemmode laufen – also Treiber oder sonstigen Kernelprogrammcode.
3. Sie lassen gerade einen spezielen „Tue nix“ Programmcode laufen – die sogenante Idle Loop. Das ist ein Programmcode im Kernel (pm_idle()) der die CPU sinnlos im Kreis hüpfen lasst (vereinfacht gesagt).

Was soll nun also IO-Wait sein?
Eine Festplatte ist im Regelfall so um den Faktor 1000 langsamer als eine CPU. Wenn also eine CPU einen IO-Request los schickt dann dauert es für sie gefühlte Stunden bis Tage bis eine Antwort da ist.
Die CPU kann in dieser Zeit ihren aktuellen Prozess nicht fortführen – denn der braucht ja das Ergebnis der Festplatte.
Was aber nicht heißt dass unsere CPU zum nichtstun verdammt ist, sie wird vom Betriebssystem Sheduler einfach verwendet um etwas anderes zu tun. z.B. einen anderen Prozess laufen zu lassen. Oder die IDLE-Loop!

Und erst wenn die Festplatte irgendwann (Tage später) mit einem Interrupt um die Ecke kommt kann der Prozess der den IO gemacht hat weiterlaufen. Ob der Prozess nun die gleiche CPU bekommt oder eine andere ist dann absolut unerheblich.

Es ist also soweit klar: Eine CPU wartet nicht auf IO.
Was ist nun aber IO-Wait?

Nach einiger Suche habe ich eine Seite gefunden die das mit einem Experiment erklärt.
Wir nehmen und ein Testsystem und schauen uns vmstat an:
(vmstat 1)

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      0 24206176  16948 207236    0    0   186     4   48   50  0  1 98  1  0
 0  0      0 24206408  16948 207236    0    0     0     0   72  110  0  0 100  0  0
 0  0      0 24206440  16948 207236    0    0     0     0   87  140  0  0 100  0  0
 0  0      0 24206440  16948 207236    0    0     0     0   54   88  0  0 100  0  0
 0  0      0 24206440  16948 207236    0    0     0     0   81  132  0  0 100  0  0

Das System ist also mal ganz deutlich am nichtstun.
Jetzt geben wir dem ersten Prozessor mal deutlich arbeit – dank dem Kommando ‚taskset‘ auch NUR dem ersten Prozessor:

taskset 1 dd if=/dev/vda of=/dev/null bs=1MB

Was sehen wir nun in vmstat?

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  1      0 23008656 1209688 209572    0    0   311     1   22   25  0  0 100  0  0
 0  1      0 22622788 1594328 210708    0    0 384384     0 5877 2575  0  3 88 10  0
 1  0      0 22244648 1971544 211296    0    0 377344     0 5787 2602  0  3 87 10  0
 1  0      0 21905764 2309728 212208    0    0 338176    12 5156 2475  0  2 88 10  0
 1  0      0 21494396 2720096 213188    0    0 410368     0 6369 2594  0  3 87  9  1
 0  1      0 21112760 3101024 214064    0    0 380800     0 5703 2354  0  3 88 10  0
 1  0      0 20567044 3645408 215468    0    0 544512     0 8473 4362  0  5 87  8  0

Aha! Ca. 12% unserer CPUs arbeiten. Davon ca. 2% im Systemmode und 10% im IOWait. Bei einem 8 Prozessor System ist das erwartet.
Um das ganze noch per Prozessor zu sehen (vmstat kann das leider nicht pro Prozessor aufschlüsseln) hilft „mpstat -P ALL“ oder „top“ mit dem Drücken von „1“ nach dem Start.
Hier zeigt sich dass die erste CPU hauptsächlich IO-Wait macht:

%Cpu0  :  0.0 us, 72.5 sy,  0.0 ni,  0.0 id, 26.4 wa,  0.0 hi,  0.0 si,  1.0 st

Und jetzt kommt der Trick. Mit einem weiteren Kommando bringen wir wieder die erste CPU dazu mächtig Programmcode auszuführen:

taskset 1 sh -c "while true; do true; done"

Und was zeigt sich nun im vmstat und top?

 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 3  1      0 139256 23772920 509164    0    0 51894     0  845  333  0  5 94  1  0
 2  0      0 132016 23780232 508856    0    0 506112     0 8506 3675  8  5 87  0  0
 2  1      0 129492 23782704 509180    0    0 460672     0 7718 4241  8  5 87  0  1
 2  0      0 130296 23781712 508732    0    0 439936     0 7394 2748  8  5 87  0  0
 2  0      0 133728 23778304 508964    0    0 472064     0 7960 5470  8  6 87  0  0

Sieh an, da kommen plötzlich 8% Usermode dazu…
Und in Top?

%Cpu0  : 61.7 us, 37.7 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.7 st

AHA! Auch hier: Unsere CPU macht ordentlich Programmcode und wartet plötzlich nicht mehr auf IO.

Und die Erfahrung hierraus?
IO-Wait bedeutet eigentlich nur „Diese CPU ist gerade Idle, hat aber bevor sie Idle gegangen ist einen IO-Request abgeschickt.“
Eine CPU die also IO-Wait macht ist durchaus noch voll verfügbar!

Und hier die Seite wo ich das herhabe: The precise meaning of I/O wait time in Linux

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.