Guía de seguimiento dinámico de Solaris

Capítulo 9 Adiciones

Al realizar la instrumentación del sistema para responder a preguntas relacionadas con el rendimiento, es recomendable tener en cuenta cómo se van a agregar los datos para responder a una pregunta específica, en lugar de pensar en la recopilación de datos realizada por sondeos individuales. Por ejemplo, si desea saber el número de llamadas del sistema por Id. de usuario, no es necesario que consulte el dato recopilado en cada llamada del sistema, sino que, simplemente, puede ver una tabla de Id. de usuario y llamadas del sistema. Anteriormente, respondería a esta pregunta recopilando los datos en cada llamada del sistema y realizando un procesamiento posterior de los mismos con una herramienta como, por ejemplo, awk(1) o perl(1). Sin embargo, en DTrace, la adición de datos es una operación de primer orden. En este capítulo, se describen las utilidades de DTrace para manipular adiciones.

Funciones de adición

Una función de adición tiene la siguiente propiedad:

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

donde xn es un conjunto de datos arbitrario. Es decir, al aplicar una función de adición a los subconjuntos del conjunto completo, y a continuación, al aplicarla de nuevo a los resultados, se ofrece el mismo resultado que al aplicarla al conjunto completo. Por ejemplo, considere una función SUM que ofrece la suma de un conjunto de datos específico. Si los datos sin procesar están compuestos por {2, 1, 2, 5, 4, 3, 6, 4, 2}, el resultado de la aplicación de SUM a todo el conjunto es {29}. Del mismo modo, el resultado de la aplicación de SUM al subconjunto de los tres primeros elementos es {5}, el resultado de la aplicación de SUM al conjunto compuesto por los tres elementos siguientes es {12} y el resultado de la aplicación de SUM a los tres elementos restantes es también {12}. SUM es una función de adición, ya que al aplicarla al conjunto de estos resultados, {5, 12, 12}, obtenemos el mismo resultado, {29}, que al aplicar SUM a los datos originales.

No todas las funciones son funciones de adición. Un ejemplo de una función que no es de adición es MEDIAN que determina el elemento medio del conjunto. (El elemento medio se define como el elemento de un conjunto que cuenta con tantos elementos superiores como inferiores a él dentro del conjunto.) La función MEDIAN se deriva de la ordenación del conjunto y la selección del elemento medio. Si volvemos al ejemplo anterior con los datos originales sin procesar, al aplicar MEDIAN a un conjunto compuesto por los tres primeros elementos, el resultado es {2}. (El conjunto ordenado es {1, 2, 2}; {2} es el conjunto compuesto por el elemento medio.) Del mismo modo, al aplicar MEDIAN a los tres elementos siguientes, obtenemos como resultado {4} y al aplicar MEDIAN a los tres elementos finales, el resultado es {4}. Por lo tanto, al aplicar MEDIAN a cada uno de los subconjuntos, el resultado es el conjunto {2, 4, 4}. Si aplicamos MEDIAN a este conjunto, obtenemos como resultado {4}. Sin embargo, si ordenamos el conjunto original, el resultado es {1, 2, 2, 2, 3, 4, 4, 5, 6}. Al aplicar MEDIAN a este conjunto, el resultado es {3}. Como los resultados no coinciden, MEDIAN no es una función de adición.

Muchas de las funciones habituales para conocer un conjunto de datos son funciones de adición. Entre estas funciones, se incluyen el recuento del número de elementos en el conjunto, el cálculo del valor mínimo y el valor máximo del conjunto, y la suma de todos los elementos del conjunto. La media aritmética del conjunto puede obtenerse a partir de la función que permite realizar un recuento del número de elementos del conjunto y de la función que permite sumar el número de elementos del conjunto.

Sin embargo, algunas funciones de utilidad no son funciones de adición. Entre estas funciones se incluyen el cálculo del modo (el elemento más común) de un conjunto, el valor medio del conjunto o la desviación estándar del conjunto.

La aplicación de funciones de adición a datos mientras se realiza el seguimiento tiene varias ventajas:

Adiciones

DTrace almacena los resultados de las funciones de adición en objetos denominados adiciones. Los resultados de la adición se indexan mediante una tupla de expresiones similares a las utilizadas para las matrices asociativas. En D, la sintaxis de una adición es:

@name[ keys ] = aggfunc ( args );

donde name es el nombre de la adición, keys es una lista separada por comas de expresiones del lenguaje D, aggfunc es una de las funciones de adición de DTrace y args es una lista separada por comas de los argumentos adecuados para la función de adición. La variable de adición name es un identificador de D que incluye, al principio, el carácter especial @. Todas las adiciones con nombre de los programas D son variables globales; no existe ninguna adición local de cláusula o subproceso. Los nombres de las adiciones se mantienen en espacios de nombres de identificadores distintos de las otras variables globales de D. Recuerde que a y @a no son la misma variable si vuelve a utilizar los nombres. El nombre de adición especial @ puede utilizarse para asignar un nombre a una adición anónima en programas D sencillos. El compilador del lenguaje D considera este nombre un alias del nombre de adición @_.

Las funciones de adición de DTrace se muestran en la siguiente tabla. La mayoría de las funciones de adición utilizan un solo argumento que representa el nuevo dato.

Tabla 9–1 Funciones de adición de DTrace

Nombre de la función 

Argumentos 

Resultado 

count

ninguno 

El número de veces que se ha realizado una llamada a una función. 

sum

expresión escalable 

El valor total de las expresiones especificadas. 

avg

expresión escalable 

La media aritmética de las expresiones especificadas. 

min

expresión escalable 

El valor inferior entre las expresiones especificadas. 

max

expresión escalable 

El valor superior entre las expresiones especificadas. 

lquantize

expresión escalable, límite inferior, límite superior, valor del paso 

Una distribución de frecuencia lineal, clasificada según el tamaño en el intervalo indicado, de los valores de las expresiones especificadas. Incrementa el valor del compartimento superior, que es inferior a la expresión especificada.

quantize

expresión escalable 

Una distribución de frecuencia de potencias de dos de los valores de las expresiones especificadas. Incrementa el valor del compartimento superior de potencias de dos, que es inferior a la expresión especificada.

Por ejemplo, para realizar el recuento de las llamadas de sistema write(2) en el mismo, puede utilizar una cadena de carácter informativo como clave y la función de adición count():

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

El comando dtrace imprime de forma predeterminada los resultados de la adición cuando finaliza el proceso, ya sea como resultado de una acción END específica o cuando el usuario pulsa Control-C. La siguiente salida de ejemplo muestra el resultado de la ejecución de este comando, al esperar unos segundos y pulsar Control-C:


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

  write system calls                                              179
#

Puede realizar un recuento de las llamadas del sistema por nombres de procesos utilizando la variable execname como clave en una adición:

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

En la siguiente salida de ejemplo, se muestra el resultado de la ejecución de este comando, al esperar varios segundos y pulsar 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
#

También es posible que desee examinar más detalladamente las acciones de escritura organizadas por el nombre del archivo ejecutable y el descriptor de archivo. El descriptor del archivo es el primer argumento de write(2), por lo que, en el siguiente ejemplo, se utiliza una clave formada por execname y arg0:

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

Al ejecutar este comando, se genera una tabla con el nombre del archivo ejecutable y el descriptor de archivo, como se muestra en el siguiente ejemplo:


# 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
#

En el siguiente ejemplo, se muestra el tiempo medio que ha durado la llamada del sistema de escritura, organizado por el nombre de proceso. En este ejemplo se utiliza la función de adición avg(), especificando la expresión que permite calcular el promedio como argumento. En este ejemplo, se calcula el promedio del tiempo cronometrado que ha durado la llamada del sistema:

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

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

En la siguiente salida de ejemplo, se muestra el resultado de la ejecución de este comando, al esperar varios segundos y pulsar 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
#

El promedio puede resultar de utilidad, pero, a menudo, no ofrece suficiente información para conocer la distribución de los puntos de datos. Para conocer detalladamente la distribución, utilice la función de adición quantize(), como se muestra en el siguiente ejemplo:

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

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

Como cada línea de salida se convierte en un diagrama de distribución de frecuencia, el resultado de esta secuencia de comandos es considerablemente más largo que los anteriores. En el siguiente ejemplo, se muestra una selección de la salida de muestra:


  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        

Tenga en cuenta que las filas de la distribución de frecuencia están formadas siempre por valores de potencias de dos. Cada fila indica el recuento del número de elementos superiores o iguales al valor correspondiente, pero inferiores al valor superior de la fila siguiente. Por ejemplo, el resultado anterior muestra que iropt presentaba 4.149 operaciones de escritura que han tardado en realizarse entre 8.192 y 16.383 nanosegundos, incluidos estos dos valores.

Mientras que quantize() es útil para obtener una perspectiva rápida de los datos, es posible que desee examinar, en su lugar, una distribución entre valores lineales. Para mostrar una distribución de valores lineales, utilice la función de adición lquantize. () La función lquantize() utiliza tres argumentos, además de una expresión de D: un límite inferior, un límite superior y un paso. Por ejemplo, si desea consultar la distribución de operaciones de escritura por descriptor de archivo, no resultaría eficaz realizar una cuantificación de potencias de dos. En su lugar, utilice una cuantificación lineal con un intervalo reducido, como se muestra en el siguiente ejemplo:

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

Al ejecutar esta secuencia de comandos durante varios segundos, se obtiene como resultado una gran cantidad de información. En el siguiente ejemplo, se muestra una selección de la salida habitual:


  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        

También puede utilizar la función de adición lquantize() para realizar una adición en el tiempo a partir de un punto del pasado. Esta técnica permite supervisar un cambio en el comportamiento a lo largo del tiempo. En el ejemplo siguiente, se muestra un cambio en el comportamiento de las llamadas del sistema durante la duración de un proceso que está ejecutando el comando 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;
}

La secuencia de comandos anterior proporciona información detallada sobre el comportamiento de las llamadas del sistema cuando se ejecutan varios procesos date(1). Para ver este resultado, ejecute sh -c 'while true; do date >/dev/null; done' en una ventana, mientras ejecuta la secuencia de comandos de D en otra. Esta secuencia de comandos genera un perfil del comportamiento de las llamadas del sistema del comando 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        

Este resultado proporciona una idea general de las diferentes fases del comando date(1) en relación con los comandos necesarios del núcleo. Para conocer mejor estas fases, es posible que desee conocer las llamadas del sistema que se están realizando en cada momento. Si es así, puede cambiar la secuencia de comandos de D para realizar la adición en la variable probefunc en lugar de en una cadena constante.

Impresión de las adiciones

De forma predeterminada, se muestran varias adiciones en el orden en el que se han introducido en el programa D. Puede anular este comportamiento mediante la función printa() para imprimir las adiciones. La función printa() también permite dar formato de forma precisa a los datos de la adición utilizando una cadena de formato, como se describe en el Capítulo 12Formato de salida.

Si se da formato a la adición con una instrucción printa() en el programa D, el comando dtrace realizará una captura de los datos de la adición e imprimirá los resultados, una vez completado el seguimiento, con el formato de adición predeterminado. Si se da formato a una adición específica con la instrucción printa(), se deshabilita el comportamiento predeterminado. Puede obtener resultados equivalentes si agrega la instrucción printa(@nombre_adición) a la cláusula de sondeo dtrace:::END del programa. El formato de salida predeterminado de las funciones de adición avg(), count(), min(), max() y sum() muestra un valor decimal entero que se corresponde con el valor agregado para cada tupla. El formato de salida predeterminado de las funciones de adición lquantize() y quantize() muestra una tabla ASCII de los resultados. Las tuplas de adición se imprimen de forma similar a si se hubiera aplicado trace() a cada elemento de la tupla.

Normalización de los datos

Al agregar datos a lo largo de un periodo de tiempo amplio, es posible que desee normalizar los datos en relación a algún factor constante. Esta técnica permite comparar los datos separados de forma más sencilla. Por ejemplo, al agregar llamadas del sistema, es posible que desee obtener como resultado las llamadas del sistema con una tasa por segundo en lugar de un valor absoluto que englobe todo el periodo completo. La acción normalize() de DTrace permite normalizar los datos de esta manera. Los parámetros de normalize() incluyen una adición y un factor de normalización. El resultado de la adición muestra cada valor dividido por el factor de normalización.

En el siguiente ejemplo, se muestra cómo agregar datos por llamada del sistema:

#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);
}

Al ejecutar la secuencia de comandos anterior durante un breve periodo de tiempo, se obtiene como resultado la siguiente salida en el equipo de escritorio:


# 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() establece el factor de normalización para la adición especificada, pero esta acción no modifica los datos subyacentes. La acción denormalize() sólo utiliza una adición. Al agregar la acción de anulación de la normalización al ejemplo anterior, se devuelven los recuentos de llamadas del sistema sin procesar y las tasas por segundo:

#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);
}

Al ejecutar la secuencia de comandos anterior durante un breve periodo de tiempo, se obtiene un resultado similar al siguiente ejemplo:


# 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

Las adiciones también pueden volver a normalizarse. Si se llama a normalize() más de una vez para una misma adición, se utilizará el factor de adición especificado en la llamada más reciente. En el siguiente ejemplo, se imprimen las tasas por segundo durante un periodo de tiempo:


Ejemplo 9–1 renormalize.d: volver a normalizar una adición.

#pragma D option quiet

BEGIN
{
	start = timestamp;
}

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

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

Eliminación de las adiciones

Al utilizar DTrace para crear secuencias de comandos de supervisión simples, puede borrar periódicamente los valores de la adición mediante la función clear(). Esta función utiliza una adición como único parámetro. La función clear() sólo borra los valores de la adición, aunque sus claves se mantienen. Por lo tanto, la presencia de una clave en una adición con un valor cero asociado indica que la clave tenía un valor distinto a cero que, posteriormente, se ha establecido en cero como parte de la función clear(). Para descartar tanto los valores como las claves de la adición, utilice la función trunc(). Consulte Truncamiento de las adiciones para obtener más información.

En el ejemplo siguiente se agrega clear() al Ejemplo 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;
}

Mientras que en el Ejemplo 9–1 se muestra la tasa de llamadas del sistema durante el período de vida de la llamada a dtrace, en el ejemplo anterior se muestra la tasa de llamadas del sistema sólo durante el período de diez segundos más reciente.

Truncamiento de las adiciones

Al consultar los resultados de la adición, es habitual que sólo se interese por los resultados de nivel superior. Las claves y los valores asociados a otros que no sean los de nivel superior no son interesantes. Es posible que también desee descartar el resultado de toda una adición, eliminando las claves y los valores. La función trunc() de DTrace se utiliza en estas dos situaciones.

Los parámetros de trunc() son una adición y un valor de truncamiento opcional. Sin el valor de truncamiento, trunc() descarta tanto los valores de adición como las claves para toda la adición. Cuando hay un valor de truncamiento n, trunc() descarta los valores y las claves de adición, excepto los asociados a los n valores superiores. En otras palabras, trunc(@foo, 10) trunca la adición denominada foo después de los diez valores superiores, mientras que trunc(@foo) descarta toda la adición. También se descarta toda la adición si se ha especificado 0 como valor de truncamiento.

Para ver los n valores inferiores en lugar de los n valores superiores, especifique un valor de truncamiento negativo en trunc(). Por ejemplo, trunc(@foo, -10) trunca la adición denominada foo después de los diez valores inferiores.

El siguiente ejemplo aumenta el ejemplo de llamadas del sistema para mostrar únicamente la tasa de llamadas del sistema por segundo de las diez aplicaciones principales que llaman al sistema durante un periodo de diez segundos:

#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;
}

En el siguiente ejemplo, se muestra el resultado de la ejecución de la secuencia de comandos anterior en un equipo portátil con un nivel bajo de carga:


  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

Minimización de las anulaciones

Dado que DTrace almacena en la memoria intermedia algunos datos de la adición contenidos en el núcleo, es posible que no haya espacio disponible cuando se añada una nueva clave a la adición. En ese caso, se omiten los datos, aumenta el contador y dtrace genera un mensaje que indica la anulación de la adición. Esta situación no suele producirse habitualmente, ya que DTrace mantiene un estado de ejecución amplia (compuesto por la clave de la adición y el resultado inmediato) en el nivel de usuario donde el espacio puede aumentar dinámicamente. En el improbable caso de que se produzca una anulación de la adición, puede aumentar el tamaño de la memoria intermedia de la adición con la opción aggsize para reducir las probabilidades de que se produzcan anulaciones. También puede utilizar esta opción para reducir al mínimo la huella de memoria de DTrace. Al igual que con cualquier opción de tamaño, aggsize puede especificarse con cualquier sufijo de tamaño. La opción bufresize establece la directiva de cambio de tamaño de esta memoria intermedia. Para obtener más información sobre la memoria intermedia y principal y las directivas de memoria intermedia, consulte el Capítulo 11Memorias intermedias y almacenamiento en memoria intermedia. Para obtener más información sobre las opciones, consulte el Capítulo 16Opciones y optimizables.

Otro método para evitar anulaciones de la adición consiste en aumentar la tasa con la que se consumen los datos de la adición en el nivel de usuario. Esta tasa se establece de forma predeterminada en una vez por segundo y puede ajustarse de forma explícita con la opción aggrate. Al igual que con cualquier opción de tasa, aggrate puede especificarse con cualquier sufijo de tiempo, aunque se establece de forma predeterminada en tasa por segundo. Para obtener más información sobre la opción aggsize, consulte el Capítulo 16Opciones y optimizables.