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