Lors du groupement de données sur une période donnée, vous souhaitez certainement normaliser les données en fonction d'un facteur constant. Cette technique permet de comparer des données disjointes plus facilement. Par exemple, lors du groupement d'appels système, vous souhaitez certainement afficher comme sortie les appels système en tant que vitesse par seconde au lieu d'une valeur absolue au cours de l'exécution. L'action normalize() de DTrace vous permet ainsi de normaliser des données. Les paramètres sur lesquels doit s'appliquer la fonction normalize() sont un facteur de groupement et de normalisation. La sortie du groupement présente chaque valeur divisée par le facteur de normalisation.
L'exemple suivant présente la méthode de groupement des données par appel système :
#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); }
L'exécution du script ci-dessus pendant une brève période permet d'obtenir la sortie suivante sur un ordinateur de bureau :
# 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 |
La fonction normalize() définit le facteur de normalisation pour le groupement spécifié, mais cette action ne modifie pas les données sous-jacentes. La fonction denormalize() prend uniquement un groupement. L'ajout de l'action d'annulation de la normalisation à l'exemple précédent renvoie le nombre d'appels système brut ainsi que la vitesse par seconde :
#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); }
L'exécution du script ci-dessus pendant une brève période permet d'obtenir une sortie similaire à l'exemple suivant :
# 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 |
Les groupements peuvent également être renormalisés. Si la fonction normalize() est appelée plusieurs fois pour le même groupement, le facteur de normalisation sera le facteur spécifié dans l'appel le plus récent. L'exemple suivant imprime les vitesses par seconde au fil du temps :
#pragma D option quiet BEGIN { start = timestamp; } syscall:::entry { @func[execname] = count(); } tick-10sec { normalize(@func, (timestamp - start) / 1000000000); printa(@func); }