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.
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:
No es necesario almacenar todo el conjunto de datos. Cada vez que vaya a agregarse un nuevo elemento al conjunto, se calcularán las funciones de adición en función del conjunto compuesto por el resultado intermedio actual y el nuevo elemento. Una vez calculado el nuevo resultado, puede descartarse el nuevo elemento. Este proceso reduce la cantidad de almacenamiento necesario para un factor del número de puntos de datos, que, a menudo, suele ser de gran tamaño.
La recopilación de datos no provoca problemas de escalabilidad patológicos. Las funciones de adición permiten que los resultados intermedios se conserven por CPU en lugar de en una estructura de datos compartida. DTrace aplica a continuación la función de adición al conjunto compuesto por los resultados intermedios por CPU para generar el resultado final de todo el sistema.
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.
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.
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:
#pragma D option quiet BEGIN { start = timestamp; } syscall:::entry { @func[execname] = count(); } tick-10sec { normalize(@func, (timestamp - start) / 1000000000); printa(@func); }
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.
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 |
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.