Manuel de suivi dynamique Solaris

Chapitre 9 Groupements

Lors de l'instrumentation du système en vue de répondre aux questions portant sur les problèmes de performance, il est utile d'envisager comment le groupement de données permet de répondre à une question spécifique, plutôt que de raisonner en termes de rassemblement de données par des sondes individuelles. Par exemple, si vous souhaitez connaître le nombre d'appels système par ID utilisateur, vous n'avez pas nécessairement besoin de connaître les données recueillies au niveau de chaque appel système. Seule la consultation d'un tableau des ID utilisateur et des appels système présente pour vous un intérêt. Auparavant, pour répondre à cette question, vous deviez rassembler les données obtenues au niveau de chaque appel système pour procéder ensuite au post-traitement des données à l'aide d'un outil comme awk(1) ou perl(1). Cependant, dans DTrace, le groupement de données constitue une opération de première classe. Ce chapitre décrit les fonctions de DTrace permettant de manipuler les groupements.

Fonctions de groupement

Une fonction de groupement se caractérise par les propriétés suivantes :

f(f(x0) U f(x 1) U ... U f(xn)) = f(x 0 U x1  U ... U xn)

xn est un jeu de données arbitraires. En bref, appliquer une fonction de groupement à des sous-ensembles puis la réappliquer aux résultats obtenus revient à l'appliquer à l'intégralité des données. Par exemple, prenons une fonction SUM permettant d'additionner un jeu de données. Si les données brutes se composent des éléments {2, 1, 2, 5, 4, 3, 6, 4, 2}, on obtient {29} en appliquant la fonction SUM à l'intégralité du jeu. De la même façon, l'application de SUM au sous-ensemble comprenant les trois premiers éléments donne comme résultat {5}, l'application de SUM à l'ensemble comprenant les trois éléments suivants donne comme résultat {12} et l'application de SUM aux trois éléments restants donne également comme résultat {12}. SUM est une fonction de groupement car son application à l'ensemble formé par les résultats {5, 12, 12} donne le même résultat, {29}, que l'application de SUM aux données d'origine.

Toutes les fonctions ne sont pas des fonctions de groupement. C'est notamment le cas de la fonction MEDIAN : elle détermine la valeur médiane d'un jeu de données. (La médiane se caractérise comme l'élément d'un ensemble ayant une valeur telle qu'il existe autant d'éléments dont la valeur est supérieure à la sienne que d'éléments dont la valeur est inférieure à la sienne.) La fonction MEDIAN est calculée en triant l'ensemble et en sélectionnant l'élément central. Si l'on revient aux données brutes d'origine, l'application de la fonction MEDIAN à l'ensemble comprenant les trois premiers éléments donne comme résultat {2}. (L'ensemble trié donne {1, 2, 2} ; {2} constitue l'élément central de l'ensemble.) De même, l'application de la fonction MEDIAN aux trois éléments suivants donne comme résultat {4} et son application aux trois derniers éléments donne comme résultat {4}. L'application de MEDIAN à chacun des sous-ensembles donne donc {2, 4, 4}. Le résultat donné par l'application de MEDIAN à cet ensemble est {4}. Toutefois, le tri de l'ensemble d'origine donne comme résultat {1, 2, 2, 2, 3, 4, 4, 5, 6}. L'application de MEDIAN à cet ensemble donne donc comme résultat {3}. Étant donné que les résultats ne correspondent pas, MEDIAN n'est pas une fonction de groupement.

De nombreuses fonctions courantes permettant d'interpréter un jeu de données sont des fonctions de groupement. Ces fonctions permettent entre autres de compter le nombre d'éléments dans un ensemble, de calculer les valeurs minimale et maximale d'un ensemble et d'additionner l'ensemble des éléments au sein de cet ensemble. Il est possible de déterminer la signification arithmétique à partir de la fonction permettant de compter le nombre d'éléments dans l'ensemble et celle permettant d'additionner le nombre d'éléments dans l'ensemble.

Toutefois, plusieurs fonctions utiles ne sont pas des fonctions de groupement, comme par exemple les fonctions permettant de calculer le mode (l'élément le plus courant) d'un ensemble, sa valeur médiane ou son écart type.

L'application de fonctions de groupement à des données alors qu'elles font l'objet d'un suivi présente de nombreux avantages :

Groupements

DTrace stocke les résultats des fonctions de groupement dans des objets appelés groupements. Les résultats des groupements sont indexés avec un tuple d'expressions similaires à celles utilisées pour les tableaux associatifs. En D, la syntaxe d'un groupement est la suivante :

@name[ keys ] = aggfunc ( args );

name est le nom du groupement, keys est une liste d'expressions D, séparées par des virgules, aggfunc est l'une des fonctions de groupement DTrace et args est une liste d'arguments séparés par des virgules, correspondant à la fonction de groupement. Le groupement nameest un identificateur D ayant comme préfixe le caractère spécial @. Tous les groupements de vos programmes D sont des variables globales ; il n'existe pas de groupement local de clause ou de thread. Les noms de groupement sont conservés dans un espace de noms d'identificateurs séparé des autres variables globales D. N'oubliez pas que a et @a ne sont pas la même variable si vous réutilisez les noms. Le nom de groupement spécial @ peut être utilisé pour nommer un groupement anonyme avec des programmes D simples. Le compilateur D traite ce nom en tant qu'alias du nom de groupement @_.

Les fonctions de groupement DTrace sont affichées dans le tableau suivant. La plupart des fonctions de groupement ne prennent qu'un seul argument représentant la nouvelle donnée.

Tableau 9–1 Fonctions de groupement DTrace

Nom de la fonction 

Arguments 

Résultat 

count

aucun 

Nombre d'appels. 

sum

expression scalaire 

Valeur totale des expressions spécifiées. 

avg

expression scalaire 

Moyenne arithmétique des expressions spécifiées. 

min

expression scalaire 

Valeur la plus faible parmi les expressions spécifiées. 

max

expression scalaire 

Valeur la plus élevée parmi les expressions spécifiées. 

lquantize

expression scalaire, limite inférieure, limite supérieure, valeur d'étape 

Répartition linéaire des fréquences, comprises dans la plage spécifiée, des valeurs des expressions spécifiées. Incrémente la valeur dans le compartiment inférieur le plus proche de l'expression spécifiée.

quantize

expression scalaire 

Répartition des fréquences multiples de deux des valeurs des expressions spécifiées. Incrémente la valeur dans le compartiment multiple de deux inférieur le plus proche de l'expression spécifiée.

Par exemple, pour compter le nombre d'appels système write(2) dans le système, vous pouvez utiliser une chaîne informative en tant que clé ainsi que la fonction de groupement count() :

syscall::write:entry
{
	@counts["write system calls"] = count();
}

La commande dtrace affiche les résultats du groupement par défaut lorsque le processus se termine, soit en tant que résultat d'une action explicite END, soit lorsque l'utilisateur appuie sur Control-C. L'exemple de sortie suivant montre le résultat de l'exécution de cette commande, après une attente de quelques secondes et après avoir appuyé sur Control-C :


# dtrace -s writes.d
dtrace: script './writes.d' matched 1 probe
^C

  write system calls                                              179
#

Vous pouvez compter les appels système par nom de processus en utilisant la variable execname en tant que clé à un groupement :

syscall::write:entry
{
	@counts[execname] = count();
}

L'exemple de sortie suivant montre le résultat de l'exécution de cette commande, après une attente de quelques secondes et après avoir appuyé sur Control-C :


# dtrace -s writesbycmd.d
dtrace: script './writesbycmd.d' matched 1 probe
^C

  dtrace                                                            1
  cat                                                               4
  sed                                                               9
  head                                                              9
  grep                                                             14
  find                                                             15
  tail                                                             25
  mountd                                                           28
  expr                                                             72
  sh                                                              291
  tee                                                             814
  def.dir.flp                                                    1996
  make.bin                                                       2010
#

Vous pouvez également vouloir examiner de manière plus approfondie les saisies, organisées par nom exécutable et descripteur de fichier. Le descripteur de fichier est le premier argument de write(2) ; l'exemple suivant utilise donc une clé comprenant à la fois execname et arg0 :

syscall::write:entry
{
	@counts[execname, arg0] = count();
}

L'exécution de cette commande génère un tableau comprenant le nom exécutable et le descripteur de fichier, comme illustré dans l'exemple suivant :


# dtrace -s writesbycmdfd.d
dtrace: script './writesbycmdfd.d' matched 1 probe
^C

  cat                                                               1      58
  sed                                                               1      60
  grep                                                              1      89
  tee                                                               1     156
  tee                                                               3     156
  make.bin                                                          5     164
  acomp                                                             1     263
  macrogen                                                          4     286
  cg                                                                1     397
  acomp                                                             3     736
  make.bin                                                          1     880
  iropt                                                             4    1731
#

L'exemple suivant affiche le temps moyen écoulé lors de l'appel système en écriture, par nom de processus. Cet exemple utilise la fonction de groupement avg(), en spécifiant l'expression sur laquelle effectuer le calcul de la moyenne en tant qu'argument. L'exemple fait la moyenne du temps écoulé dans l'appel système :

syscall::write:entry
{
	self->ts = timestamp;
}

syscall::write:return
/self->ts/
{
	@time[execname] = avg(timestamp - self->ts);
	self->ts = 0;
}

L'exemple de sortie suivant montre le résultat de l'exécution de cette commande, après une attente de quelques secondes et après avoir appuyé sur Control-C :


# dtrace -s writetime.d
dtrace: script './writetime.d' matched 2 probes
^C

  iropt                                                         31315
  acomp                                                         37037
  make.bin                                                      63736
  tee                                                           68702
  date                                                          84020
  sh                                                            91632
  dtrace                                                       159200
  ctfmerge                                                     321560
  install                                                      343300
  mcs                                                          394400
  get                                                          413695
  ctfconvert                                                   594400
  bringover                                                   1332465
  tail                                                        1335260
#

La moyenne peut s'avérer utile, mais c'est un élément qui ne fournit pas suffisamment de détails pour comprendre la répartition des points de données. Pour mieux comprendre la répartition, utilisez la fonction de groupement quantize(), comme illustré dans l'exemple suivant :

syscall::write:entry
{
	self->ts = timestamp;
}

syscall::write:return
/self->ts/
{
	@time[execname] = quantize(timestamp - self->ts);
	self->ts = 0;
}

Étant donné que chaque ligne de sortie devient un diagramme de répartition de fréquences, ce script affiche une sortie nettement plus longue que les précédents : L'exemple suivant présente une sélection de la sortie de test :


  lint                                              
           value  ------------- Distribution ------------- count    
            8192 |                                         0        
           16384 |                                         2        
           32768 |                                         0        
           65536 |@@@@@@@@@@@@@@@@@@@                      74       
          131072 |@@@@@@@@@@@@@@@                          59       
          262144 |@@@                                      14       
          524288 |                                         0        

  acomp                                             
           value  ------------- Distribution ------------- count    
            4096 |                                         0        
            8192 |@@@@@@@@@@@@                             840      
           16384 |@@@@@@@@@@@                              750      
           32768 |@@                                       165      
           65536 |@@@@@@                                   460      
          131072 |@@@@@@                                   446      
          262144 |                                         16       
          524288 |                                         0        
         1048576 |                                         1        
         2097152 |                                         0        

  iropt                                             
           value  ------------- Distribution ------------- count    
            4096 |                                         0        
            8192 |@@@@@@@@@@@@@@@@@@@@@@@                  4149     
           16384 |@@@@@@@@@@                               1798     
           32768 |@                                        332      
           65536 |@                                        325      
          131072 |@@                                       431      
          262144 |                                         3        
          524288 |                                         2        
         1048576 |                                         1        
         2097152 |                                         0        

Vous pouvez remarquer que les lignes de la répartition de fréquences sont toujours des multiples de deux. Chaque ligne indique le compte du nombre d'éléments supérieurs ou égaux à la valeur correspondante mais inférieurs à la valeur supérieure la plus proche. Par exemple, le résultat ci-dessus montre que iropt a 4,149 écritures prenant entre 8,192 nanosecondes et 16,383 nanosecondes incluses.

La fonction quantize() permet d'obtenir un aperçu rapide des données, mais vous souhaitez peut-être observer à la place une répartition linéaire des valeurs. Pour afficher une répartition linéaire des valeurs, utilisez la fonction de groupement lquantize(). La fonction lquantize() prend trois arguments, en plus d'une expression D : une limite inférieure, une limite supérieure et une étape. Par exemple, si vous souhaitez observer la répartition des écritures par descripteur de fichier, une quantification de multiples de deux n'est pas efficace. À la place, utilisez une quantification linéaire avec une plage restreinte, comme illustré dans l'exemple suivant :

syscall::write:entry
{
	@fds[execname] = lquantize(arg0, 0, 100, 1);
}

L'exécution de ce script pendant plusieurs secondes permet d'obtenir une grande quantité d'informations. L'exemple suivant montre une sélection de sortie classique :


  mountd                                            
           value  ------------- Distribution ------------- count    
              11 |                                         0        
              12 |@                                        4        
              13 |                                         0        
              14 |@@@@@@@@@@@@@@@@@@@@@@@@@                70       
              15 |                                         0        
              16 |@@@@@@@@@@@@                             34       
              17 |                                         0        

  xemacs-20.4                                       
           value  ------------- Distribution ------------- count    
               6 |                                         0        
               7 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  521      
               8 |                                         0        
               9 |                                         1        
              10 |                                         0        

  make.bin                                          
           value  ------------- Distribution ------------- count    
               0 |                                         0        
               1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  3596     
               2 |                                         0        
               3 |                                         0        
               4 |                                         42       
               5 |                                         50       
               6 |                                         0        

  acomp                                             
           value  ------------- Distribution ------------- count    
               0 |                                         0        
               1 |@@@@@                                    1156     
               2 |                                         0        
               3 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@         6635     
               4 |@                                        297      
               5 |                                         0        

  iropt                                             
           value  ------------- Distribution ------------- count    
               2 |                                         0        
               3 |                                         299      
               4 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  20144    
               5 |                                         0        

Vous pouvez également utiliser la fonction de groupement lquantize() pour regrouper le temps écoulé depuis un certain point du passé. Cette technique permet d'observer une modification de comportement au fil du temps. L'exemple suivant affiche la modification dans le comportement de l'appel système sur une durée de vie d'un processus exécutant la commande date(1) :

syscall::exec:return,
syscall::exece:return
/execname == "date"/
{
	self->start = vtimestamp;
}

syscall:::entry
/self->start/
{
	/*
	 * We linearly quantize on the current virtual time minus our
	 * process's start time.  We divide by 1000 to yield microseconds
	 * rather than nanoseconds.  The range runs from 0 to 10 milliseconds
	 * in steps of 100 microseconds; we expect that no date(1) process
	 * will take longer than 10 milliseconds to complete.
	 */
	@a["system calls over time"] =
	    lquantize((vtimestamp - self->start) / 1000, 0, 10000, 100);
}

syscall::rexit:entry
/self->start/
{
	self->start = 0;
}

Le script précédent fournit plus de détails sur le comportement de l'appel système lorsque de nombreux processus date(1) sont exécutés. Pour voir ce résultat, exécutez sh -c 'while true; do date >/dev/null; done' dans une fenêtre, tandis que le script D s'exécute dans une autre. Le script produit un profil du comportement de l'appel système de la commande date(1) :


# dtrace -s dateprof.d
dtrace: script './dateprof.d' matched 218 probes
^C

  system calls over time
           value  ------------- Distribution ------------- count    
             < 0 |                                         0        
               0 |@@                                       20530    
             100 |@@@@@@                                   48814    
             200 |@@@                                      28119    
             300 |@                                        14646    
             400 |@@@@@                                    41237    
             500 |                                         1259     
             600 |                                         218      
             700 |                                         116      
             800 |@                                        12783    
             900 |@@@                                      28133    
            1000 |                                         7897     
            1100 |@                                        14065    
            1200 |@@@                                      27549    
            1300 |@@@                                      25715    
            1400 |@@@@                                     35011    
            1500 |@@                                       16734    
            1600 |                                         498      
            1700 |                                         256      
            1800 |                                         369      
            1900 |                                         404      
            2000 |                                         320      
            2100 |                                         555      
            2200 |                                         54       
            2300 |                                         17       
            2400 |                                         5        
            2500 |                                         1        
            2600 |                                         7        
            2700 |                                         0        

Ce résultat donne une idée approximative des différentes phases de la commande date(1) par rapport aux services requis du noyau. Pour mieux comprendre ces phases, vous souhaitez peut-être comprendre quels appels système font l'objet d'un appel et à quel moment. Si c'est le cas, vous pouvez modifier le script D pour regrouper la variable probefunc à la place d'une chaîne constante.

Impression de groupements

Par défaut, plusieurs groupements s'affichent selon leur ordre d'introduction dans le programme D. Vous pouvez ignorer ce comportement en utilisant la fonction printa() pour afficher les groupements. La fonction printa() permet également de formater de façon précise les données de groupement en utilisant une chaîne de format, tel que décrit dans Chapitre12Format de sortie.

Si un groupement n'est pas formaté avec une instruction printa() dans votre programme D, la commande dtrace crée un instantané des données de groupement et affiche les résultats une fois, après l'achèvement du suivi, en utilisant le format de groupement par défaut. Si un groupement donné est formaté avec une instruction printa(), le comportement par défaut est désactivé. Vous pouvez obtenir des résultats équivalents en ajoutant l'instruction printa(@ nom-groupement) à une clause de sonde dtrace:::END dans votre programme. Le format de sortie par défaut des fonctions de groupement avg(), count(), min(), max() et sum() affiche une valeur décimale d'entier correspondant à la valeur groupée de chaque tuple. Le format de sortie par défaut des fonctions de groupement lquantize() et quantize() affiche un tableau ASCII des résultats. Les tuples de groupement sont affichés comme si la fonction trace() était appliquée à chaque élément de tuple.

Normalisation des données

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 :


Exemple 9–1 renormalize.d : renormalisation d'un groupement

#pragma D option quiet

BEGIN
{
	start = timestamp;
}

syscall:::entry
{
	@func[execname] = count();
}

tick-10sec
{
	normalize(@func, (timestamp - start) / 1000000000);
	printa(@func);
}

Effacement de groupements

Lors de l'utilisation de DTrace pour élaborer des scripts de surveillance simples, vous pouvez, de temps en temps, effacer les valeurs d'un groupement en utilisant la fonction clear(). Cette fonction prend comme unique paramètre un groupement. La fonction clear() efface uniquement les valeurs du groupement ; les clés du groupement sont conservées. Par conséquent, la présence d'une clé dans un groupement ayant une valeur associée de zéro indique que la clé avait une valeur différente de zéro qui a été ultérieurement définie sur zéro dans le cadre de l'exécution d'une fonction clear(). Pour rejeter à la fois les valeurs d'un groupement et ses clés, utilisez la fonction trunc(). Pour plus d'informations, reportez-vous à la section Troncature de groupements.

L'exemple suivant ajoute la fonction clear() à l'Exemple 9–1 :

#pragma D option quiet

BEGIN
{
	last = timestamp;
}

syscall:::entry
{
	@func[execname] = count();
}

tick-10sec
{
	normalize(@func, (timestamp - last) / 1000000000);
	printa(@func);
	clear(@func);
	last = timestamp;
}

Tandis que l'Exemple 9–1 affiche le taux d'appels système sur toute la durée de vie de l'appel dtrace, l'exemple précédent affiche le taux d'appels système uniquement sur les dix dernières secondes.

Troncature de groupements

Lorsque l'on observe des résultats de groupement, ce sont souvent les dix premiers résultats qui présentent un intérêt. Les clés et valeurs associées aux valeurs autres que les valeurs les plus élevées ne présentent pas d'intérêt. Vous souhaitez peut-être également rejeter un résultat de groupement dans son intégralité, en supprimant à la fois les clés et les valeurs. La fonction trunc() de DTrace est utilisée dans ces deux cas de figure.

Les paramètres sur lesquels appliquer la fonction trunc() sont un groupement et une valeur de troncature facultative. Sans la valeur de troncature, trunc() rejette à la fois les valeurs et les clés de groupement du groupement complet. Lorsqu'une valeur de troncature n est présente, trunc() rejette les valeurs et les clés de groupement à l'exception de celles associées aux valeurs n les plus élevées. Cela signifie que trunc(@foo, 10) tronque le groupement appelé foo après les dix premières valeurs, là où trunc(@foo) rejette le groupement dans son intégralité. Le groupement complet est également rejeté si 0 est spécifié comme valeur de troncature.

Pour afficher les valeurs n du bas au lieu de celles du haut, spécifiez une valeur de troncature négative dans trunc(). Par exemple, trunc(@foo, -10) tronque la valeur nommée foo après les dix dernières valeurs.

L'exemple suivant augmente l'exemple d'appel système pour n'afficher que le nombre d'appels système par seconde des dix premières applications d'appels système sur dix secondes :

#pragma D option quiet

BEGIN
{
	last = timestamp;
}

syscall:::entry
{
	@func[execname] = count();
}

tick-10sec
{
	trunc(@func, 10);
	normalize(@func, (timestamp - last) / 1000000000);
	printa(@func);
	clear(@func);
	last = timestamp;
}

L'exemple suivant affiche la sortie de l'exécution du script ci-dessus sur un ordinateur portable légèrement chargé :


  FvwmAuto                                                          7
  telnet                                                           13
  ping                                                             14
  dtrace                                                           27
  xclock                                                           34
  MozillaFirebird-                                                 63
  xterm                                                           133
  fvwm2                                                           146
  acroread                                                        168
  Xsun                                                            616

  telnet                                                            4
  FvwmAuto                                                          5
  ping                                                             14
  dtrace                                                           27
  xclock                                                           35
  fvwm2                                                            69
  xterm                                                            70
  acroread                                                        164
  MozillaFirebird-                                                491
  Xsun                                                           1287

Réduction des abandons

Étant donné que DTrace met en tampon certaines données de groupement dans le noyau, il risque de manquer d'espace disponible lors de l'ajout d'une nouvelle clé au groupement. Dans ce cas, les données sont abandonnées, le compteur incrémenté et dtrace génère un message indiquant l'abandon d'un groupement. Ce cas de figure ne se produit que rarement car DTrace conserve un état d'exécution longue (comprenant la clé du groupement et le résultat intermédiaire) au niveau utilisateur, où l'espace peut être augmenté de façon dynamique. Dans l'éventualité peu probable d'un abandon, vous pouvez augmenter la taille du tampon de groupement avec l'option aggsize pour réduire le risque d'abandons. Vous pouvez également utiliser cette option pour réduire l'empreinte de mémoire de DTrace. Comme c'est la cas avec toutes les options de taille, il est possible de spécifier aggsize avec n'importe quel suffixe de taille. La stratégie de redimensionnement de ce tampon est dictée par l'option bufresize. Pour de plus amples informations sur la mise en tampon, reportez-vous au Chapitre11Tampons et mise en tampon. Pour de plus amples informations sur les détails, reportez-vous au Chapitre16Options et paramètres réglables.

Une autre méthode permettant d'éliminer les abandons de groupement consiste à augmenter la vitesse de consommation des données du groupement au niveau utilisateur. Par défaut, cette vitesse est définie sur une fois par seconde. Elle peut être réglée de façon explicite avec l'option aggrate. Comme avec n'importe quelle option de vitesse, aggrate peut être spécifié avec n'importe quel suffixe temporel mais le suffixe par défaut est le nombre par seconde. Pour de plus amples informations sur l'option aggsize, reportez-vous au Chapitre16Options et paramètres réglables.