Beim Anhäufen von Daten über einen gewissen Zeitraum kann es hilfreich sein, die Daten in Bezug auf einen konstanten Faktor zu normalisieren. Dank dieser Technik lassen sich unzusammenhängende Daten leichter vergleichen. So sollen möglicherweise beim Aggregieren von Systemaufrufen die Systemaufrufe nicht als absoluter Wert über den Verlauf der Ausführung, sondern in Häufigkeit pro Sekunde angezeigt werden. Die DTrace-Aktion normalize() ermöglicht eine derartige Normalisierung der Daten. Die Parameter für normalize() sind ein Aggregat und ein Normalisierungsfaktor. Die Ausgabe der Aggregatfunktion zeigt jeden Wert dividiert durch den Normalisierungsfaktor.
Das folgende Beispiel verdeutlicht das Aggregieren von Daten nach Systemaufruf:
#pragma D option quiet BEGIN { /* * Get the start time, in nanoseconds. */ start = timestamp; } syscall:::entry { @func[execname] = count(); } END { /* * Normalize the aggregation based on the number of seconds we have * been running. (There are 1,000,000,000 nanoseconds in one second.) */ normalize(@func, (timestamp - start) / 1000000000); }
Wenn das obige Skript kurz ausgeführt wird, erhalten wir auf einem Desktoprechner die folgende Ausgabe:
# dtrace -s ./normalize.d ^C syslogd 0 rpc.rusersd 0 utmpd 0 xbiff 0 in.routed 1 sendmail 2 echo 2 FvwmAuto 2 stty 2 cut 2 init 2 pt_chmod 3 picld 3 utmp_update 3 httpd 4 xclock 5 basename 6 tput 6 sh 7 tr 7 arch 9 expr 10 uname 11 mibiisa 15 dirname 18 dtrace 40 ksh 48 java 58 xterm 100 nscd 120 fvwm2 154 prstat 180 perfbar 188 Xsun 1309 .netscape.bin 3005 |
normalize() legt den Normalisierungsfaktor für das angegebene Aggregat fest. Die zugrunde liegenden Daten werden dadurch jedoch nicht geändert. denormalize() übernimmt nur ein Aggregat. Wenn wir dem vorigen Beispiel die Denormalisierungsaktion hinzufügen, erhalten wir sowohl die unverarbeitete Anzahl der Systemaufrufe als auch die Frequenz pro Sekunde:
#pragma D option quiet BEGIN { start = timestamp; } syscall:::entry { @func[execname] = count(); } END { this->seconds = (timestamp - start) / 1000000000; printf("Ran for %d seconds.\n", this->seconds); printf("Per-second rate:\n"); normalize(@func, this->seconds); printa(@func); printf("\nRaw counts:\n"); denormalize(@func); printa(@func); }
Wenn das obige Skript kurz ausgeführt wird, erhalten wir eine ähnliche Ausgabe wie in folgendem Beispiel:
# dtrace -s ./denorm.d ^C Ran for 14 seconds. Per-second rate: syslogd 0 in.routed 0 xbiff 1 sendmail 2 elm 2 picld 3 httpd 4 xclock 6 FvwmAuto 7 mibiisa 22 dtrace 42 java 55 xterm 75 adeptedit 118 nscd 127 prstat 179 perfbar 184 fvwm2 296 Xsun 829 Raw counts: syslogd 1 in.routed 4 xbiff 21 sendmail 30 elm 36 picld 43 httpd 56 xclock 91 FvwmAuto 104 mibiisa 314 dtrace 592 java 774 xterm 1062 adeptedit 1665 nscd 1781 prstat 2506 perfbar 2581 fvwm2 4156 Xsun 11616 |
Aggregate können auch renormalisiert werden. Wenn normalize() mehrmals für dasselbe Aggregat aufgerufen wird, gilt der im neuesten Aufruf angegebene Normalisierungsfaktor. Das folgende Beispiel gibt die Häufigkeit pro Sekunde im Verlauf der Zeit aus:
#pragma D option quiet BEGIN { start = timestamp; } syscall:::entry { @func[execname] = count(); } tick-10sec { normalize(@func, (timestamp - start) / 1000000000); printa(@func); }