Platten und Storage Systeme unterstützen Tagged Command Queueing, d.h. angeschlossene Server können mehrere I/O Aufträge an die Platte oder das Storage-System senden ohne zu Warten das ältere I/O-Aufträge fertig sind. Wieviele I/O-Aufträge man an eine Platte senden darf, bevor man warten muss das ältere I/O-Aufträge abgeschlossen wurden, kann über das hdisk Attribut queue_depth unter AIX konfiguriert werden. Für viele hdisk Typen ist der Wert 20 für die queue_depth der Default-Wert. In der Regel erlauben die meisten Storage-Systeme aber noch größere Werte für die Queue-Depth.
Mit Hilfe von ProbeVue lässt sich die Auslastung der Platten-Queue sehr leicht beobachten.
Ab AIX 7.1 TL4 bzw. AIX 7.2 TL0 unterstützt AIX den I/O Probe Manager. Damit lassen sich auf einfache Weise Ereignisse im I/O Stack von AIX tracen. Wird ein I/O vom Platten-Treiber gestartet, so geschieht dies über die Funktion iostart im Kernel, der Request wird an den Adapter-Treiber weitergegeben und geht dann über den Host-Bus-Adapter an das Storage-System. Das Bearbeiten der Antwort wird von der Funktion iodone im Kernel übernommen. Der I/O Probe-Manager unterstützt (unter anderem) Proben an diesen Stellen:
@@io:disk:iostart:read:<filter>
@@io::disk:iostart:write:<filter>
@@io:disk:iodone:read:<filter>
@@io::disk:iodone:write:<filter>
Als Filter kann z.B. ein Hdisk Name wie hdisk2 angegeben werden. Die Proben-Punkte lösen dann nur Ereignisse für die Platte hdisk2 aus. Damit lässt sich schon einmal eine Aktion durchführen wann immer ein I/O für eine Hdisk beginnt oder endet. Damit könnte man z.B. messen wie lange eine I/O Operation dauert oder auch einfach nur mitzählen wieviele I/Os ausgeführt werden. In unserem Beispiel waren wir aber an der Auslastung der Platten-Queue interessiert, d.h. der Anzahl I/Os die an die Platte gesendet aber noch nicht abgeschlossen wurden. Der I/O Probe-Manager besitzt für die I/O Ereignisse iostart und iodone die Builtin-Variable __diskinfo mit den folgenden Feldern (https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.genprogc/probevue_man_io.htm):
name char* Name der Platte
…
queue_depth int Die Queue-Depth der Platte (Wert aus der ODM)
cmds_out int Anzahl der ausstehenden I/Os
…
Das Feld cmds_out gibt an wieviele I/Os an die Platte gesendet wurden, für die das I/O noch nicht abgeschlossen ist (Antwort ist noch nicht beim Server angekommen).
Mit dem folgenden Code-Abschnitt ermitteln wir die minimale, maximale und durchschnittliche Anzahl an Einträgen in der Platten-Queue:
@@io:disk:iostart:*:hdisk0 // Nur I/Os für hdisk0 berücksichtigen
{
queue = __iopath->cmds_out; // Anzahl ausstehende I/Os in Variable queue festhalten
++numIO; // Anzahl I/Os in der Variablen numIO mitzählen (wegen Durchschnittsbildung)
avg += queue; // Variable avg um Anzahl ausstehende I/Os erhöhen
if ( queue < min )
min = queue; // Überprüfen auf Minimum und gegebenenfalls setzen
if ( queue > max )
max = queue; // Überprüfen auf Maximum und gegebenenfalls setzen
}
Die ermittelten Werte geben wir dann einmal pro Sekunde mit Hilfe des Intervall Probe-Managers aus:
@@interval:*:clock:1000
{
if ( numIO == 0 )
numIO = 1; // Verhindert Division durch 0 bei der Durchschnittsbildung
if ( min > max )
min = max;
printf( "%5d %5d %5d\n" , min , avg/numIO , max );
min = 100000; // Zurücksetzen der Variablen für das nächste Intervall
avg = 0;
max = 0;
numIO = 0;
}
Das vollständige Skript ist auf unserer Webseite zum Download verfügbar: ioqueue.e.
Hier ein Beispiel-Lauf des Skriptes für die Platte hdisk13:
# ./ioqueue.e hdisk13
min avg max
1 1 2
1 1 9
1 1 2
1 1 8
1 1 2
1 1 2
1 1 8
1 1 10
1 1 2
1 1 1
1 1 10
1 1 2
1 1 11
...
Das Skript erwartet die Angabe einer hdisk als Argument und gibt dann einmal pro Sekunde die ermittelten Werte für die angegebene hdisk aus.
In der Beispiel-Ausgabe sieht man das die maximale Anzahl der Einträge in der Platten-Queue 11 ist. Eine Erhöhung des Attributes queue_depth macht daher aus Performance-Sicht keinen Sinn.
Hier ein anderes Beispiel:
# ./ioqueue.e hdisk21
min avg max
9 15 20
11 17 20
15 19 20
13 19 20
14 19 20
17 18 20
18 18 19
16 19 20
13 18 20
18 19 19
17 19 20
18 19 20
17 19 19
...
In diesem Fall wird der maximale Wert 20 (die hdisk21 hat eine queue_depth von 20) regelmäßig erreicht. Eine Erhöhung der queue_depth kann in diesem Fall zu einer Verbesserung des Durchsatzes führen.
Das Beispiel-Skript lässt sich natürlich noch beliebig erweitern, man könnte z.B. noch den Durchsatz erfassen, oder die Wartezeit von I/Os in der Wait-Queue oder auch die Position und Größe jedes I/Os auf der Platte. Das dargestellte Beispiel zeigt wie einfach man Informationen zu I/Os mit Hilfe von ProbeVue ermitteln kann.
Weitere Artikel zum Thema ProbeVue
ProbeVue: Praktische Einführung
ProveVue: Praktische Einführung II
ProbeVue in Action: Identifizieren eines Abstürzenden Prozesses
ProbeVue in Action: Überwachen der „Queue Depth“ von Platten