Guía de seguimiento dinámico de Solaris

Capítulo 26 Proveedor sched

El proveedor sched pone a su disposición sondeos relacionados con la planificación de las CPU. Dado que las CPU son el único recurso que deben consumir todos los subprocesos, el proveedor sched resulta muy útil a la hora de comprender las conductas sistémicas. Por ejemplo, mediante la utilización del proveedor sched , podrá comprender cuándo y por qué razón los subprocesos se encuentran en estados de inactividad, en ejecución, cambian su prioridad o activan a otros subprocesos.

Sondeos

Los sondeos sched se describen en la Tabla 26–1.

Tabla 26–1 Sondeos sched

Sondeo 

Descripción 

change-pri

Sondeo que se activa siempre que va a modificarse la prioridad de un subproceso. El subproceso lwpsinfo_t del subproceso es apuntado por args[0]. La prioridad actual del subproceso se encuentra en el campo pr_pri de esta estructura. El psinfo_t del proceso que contiene el subproceso es apuntado por args[1]. La nueva prioridad del subproceso se encuentra en args[2].

dequeue

Sondeo que se activa inmediatamente antes de retirar un subproceso ejecutable de una cola de espera de ejecución. El lwpsinfo_t del subproceso que se está eliminando de la cola de espera es apuntado por args[0]. El psinfo_t del proceso que contiene el subproceso es apuntado por args[1]. El cpuinfo_t de la CPU desde la que se está eliminando de la cola el subproceso es apuntado por args[2]. Si se está eliminando de la cola de ejecución un subproceso que no está asociado a ninguna CPU en concreto, el miembro cpu_id de esta estructura será -1.

enqueue

Sondeo que se activa inmediatamente antes de que se coloque en una cola de espera de ejecución un subproceso ejecutable. El lwpsinfo_t del subproceso que se está colocando en la cola de espera es apuntado por args[0]. El psinfo_t del proceso que contiene el subproceso es apuntado por args[1]. El cpuinfo_t de la CPU en la que se está colocando en cola el subproceso es apuntado por args[2]. Si se está colocando en cola de ejecución un subproceso que no está asociado a ninguna CPU en concreto, el miembro cpu_id de esta estructura será -1. El valor de args[3] es un valor booleano que indica si el subproceso se colocará al frente de la cola de ejecución. El valor no es cero si el subproceso se coloca al frente de la cola de ejecución, y cero si el subproceso se coloca al final de la cola de ejecución.

off-cpu

Sondeo que se activa cuando la CPU actual está a punto de finalizar la ejecución de un subproceso. La variable curcpu indica la CPU actual. La variable curlwpsinfo indica el subproceso que está finalizando su ejecución. La variable curpsinfo describe el proceso que contiene el subproceso actual. La estructura lwpsinfo_t del subproceso que la CPU actual ejecutará a continuación es apuntado por args[0] . El psinfo_t del proceso que contiene el siguiente subproceso es apuntado por args[1].

on-cpu

Sondeo que se activa cuando una CPU acaba de iniciar la ejecución de un subproceso. La variable curcpu indica la CPU actual. La variable curlwpsinfo indica cuál es el subproceso que está iniciando su ejecución. La variable curpsinfo describe el proceso que contiene el subproceso actual.

preempt

Sondeo que se activa inmediatamente antes de que se convierta en preemptivo el subproceso actual. Después de que se active este sondeo, el subproceso actual seleccionará un subproceso para ejecutarlo, y se activará el sondeo off-cpu para el subproceso actual. En determinados casos se convertirá en preemptivo un subproceso de una CPU, pero mientras tanto se ejecutará en otra CPU. En esta situación se activará el sondeo preempt, pero el distribuidor no será capaz de encontrar un subproceso de nivel superior para ejecutarlo y se activará el sondeo remain-cpu en lugar del sondeo off-cpu.

remain-cpu

Sondeo que se activa cuando se ha tomado una decisión de planificación, pero el distribuidor ha optado por continuar con la ejecución del subproceso actual. La variable curcpu indica la CPU actual. La variable curlwpsinfo indica cuál es el subproceso que está iniciando su ejecución. La variable curpsinfo describe el proceso que contiene el subproceso actual.

schedctl-nopreempt

Sondeo que se activa siempre que se convierte en preemptivo un subproceso y posteriormente se vuelve a colocar al frente de la cola de ejecución debido a una solicitud de control de preempción. Consulte schedctl_init(3C) para obtener más detalles sobre el control de preempción. Al igual que con preempt, off-cpu o remain-cpu se activarán después de schedctl-nopreempt. Dado que schedctl-nopreempt indica una nueva colocación del subproceso actual al frente de la cola, es más probable que remain-cpu se active después de schedctl-nopreempt que off-cpu. El lwpsinfo_t del subproceso que se está colocando en preempción es apuntado por args[0]. El psinfo_t del proceso que contiene el subproceso es apuntado por args[1].

schedctl-preempt

Sondeo que se activa cuando un subproceso que está utilizando el control de preempción se coloca en este estado a pesar de ello, y se vuelve a colocar en cola al final de la cola de ejecución. Consulte schedctl_init(3C) para obtener más detalles sobre el control de preempción. Al igual que con preempt, o off-cpu o remain-cpu se activarán después de schedctl-preempt. Al igual que con preempt (y a diferencia de schedctl-nopreempt), schedctl-preempt denota volver a colocar en cola el subproceso actual al final de la cola de ejecución. Por lo tanto, es más probable que se active off-cpu después de schedctl-preempt que remain-cpu. El lwpsinfo_t del subproceso que se está colocando en preempción es apuntado por args[0]. El psinfo_t del proceso que contiene el subproceso es apuntado por args[1].

schedctl-yield

Sondeo que se activa cuando un subproceso que tiene el control de preempción habilitado y su fracción de tiempo ha ejecutado código ampliado artificialmente para ceder la CPU a otros subprocesos. 

sleep

Sondeo que se activa inmediatamente antes de que el subproceso actual se sitúe en inactividad en un objeto de sincronización. El tipo de objeto de sincronización se encuentra en el miembro pr_stype del lwpsinfo_t apuntado por curlwpsinfo . La dirección del objeto de sincronización se encuentra en el miembro pr_wchan del lwpsinfo_t apuntado por curlwpsinfo. El significado de esta dirección es un detalle de implementación privada, pero el valor de dirección podría tratarse como un símbolo único del objeto de sincronización.

surrender

Sondeo que se activa cuando una CPU ha instruido a otra CPU para realizar una decisión de planificación – a menudo porque un subproceso de mayor prioridad se ha convertido en ejecutable. 

tick

Sondeo que se activa como parte de un registro basado en pulsos de reloj. En el registro basado en pulsos de reloj, el registro de CPU se realiza examinando qué subprocesos y procesos se encuentran en ejecución cuando se activa una interrupción de intervalo fijo. El lwpsinfo_t que corresponde al subproceso al que se asigna tiempo de CPU es apuntado por args[0]. El psinfo_t que corresponde al proceso que contiene el subproceso es apuntado por args[1] .

wakeup

Sondeo que se admite inmediatamente antes de que el subproceso actual active un subproceso en inactividad en un objeto de sincronización. El lwpsinfo_t del subproceso en inactividad es apuntado por args[0]. El psinfo_t del proceso que contiene el subproceso en actividad es apuntado por args[1]. El tipo del objeto de sincronización se encuentra en el miembro pr_stype del lwpsinfo_t del subproceso en inactividad. La dirección del objeto de sincronización se encuentra en el miembro pr_wchan del lwpsinfo_t del subproceso en inactividad. El significado de esta dirección es un detalle de implementación privada, pero el valor de dirección podría tratarse como un símbolo único del objeto de sincronización.

Argumentos

Los tipos de argumento de los sondeos sched se enumeran en la Tabla 26–2; los argumentos se describen en la Tabla 26–1.

Tabla 26–2 Argumentos del sondeo sched

Sondeo 

args[0]

args[1]

args[2]

args[3]

change-pri

lwpsinfo_t *

psinfo_t *

pri_t

— 

dequeue

lwpsinfo_t *

psinfo_t *

cpuinfo_t *

— 

enqueue

lwpsinfo_t *

psinfo_t *

cpuinfo_t *

int

off-cpu

lwpsinfo_t *

psinfo_t *

— 

— 

on-cpu

— 

— 

— 

— 

preempt

— 

— 

— 

— 

remain-cpu

— 

— 

— 

— 

schedctl-nopreempt

lwpsinfo_t *

psinfo_t *

— 

— 

schedctl-preempt

lwpsinfo_t *

psinfo_t *

— 

— 

schedctl-yield

lwpsinfo_t *

psinfo_t *

— 

— 

sleep

— 

— 

— 

— 

surrender

lwpsinfo_t *

psinfo_t *

— 

— 

tick

lwpsinfo_t *

psinfo_t *

— 

— 

wakeup

lwpsinfo_t *

psinfo_t *

— 

— 

Tal y como indica la Tabla 26–2 un alto número de sondeos sched tienen argumentos que consisten en un puntero a un lwpsinfo_t y un puntero a un psinfo_t, que indica un subproceso y el proceso que contiene el subproceso, respectivamente. Estas estructuras de describen con detalle en lwpsinfo_t y psinfo_t, respectivamente.

cpuinfo_t

La estructura cpuinfo_t define una CPU. Tal y como indica la Tabla 26–2, los argumentos de los sondeos enqueue and dequeue incluyen un puntero a un cpuinfo_t. Además, el cpuinfo_t que corresponde a la CPU actual es apuntado por la variable curcpu. La definición de la estructura cpuinfo_t es la siguiente:

typedef struct cpuinfo {
	processorid_t cpu_id;           /* CPU identifier */
	psetid_t cpu_pset;              /* processor set identifier */
	chipid_t cpu_chip;              /* chip identifier */
	lgrp_id_t cpu_lgrp;             /* locality group identifer */
	processor_info_t cpu_info;      /* CPU information */
} cpuinfo_t;

El miembro cpu_id es el identificador del proceso, tal y como devuelvepsrinfo(1M) y p_online(2).

El miembro cpu_pset es el conjunto de procesadores que contiene la CPU, en caso de contener alguno. Consulte psrset(1M) para obtener más detalles acerca de los conjuntos de procesadores.

El miembro cpu_chip es el identificador del chip físico. Los chips físicos pueden contener varias CPU. Consulte psrinfo(1M) para obtener más información.

El miembro cpu_lgrp es el identificador del grupo de latencia asociado a la CPU. Consulte liblgrp(3LIB) para obtener detalles acerca de los grupos de latencia.

El miembro cpu_info es la estructura processor_info_t asociada a la CPU, tal y como la devuelve processor_info(2).

Ejemplos

on-cpu y off-cpu

Una pregunta común que probablemente querrá ver respondida es qué CPU están ejecutando subprocesos y durante cuánto tiempo. Puede utilizar los sondeos on-cpu y off-cpu para responder fácilmente a esta pregunta en base a todo un sistema, tal y como se muestra en el siguiente ejemplo:

sched:::on-cpu
{
	self->ts = timestamp;
}

sched:::off-cpu
/self->ts/
{
	@[cpu] = quantize(timestamp - self->ts);
	self->ts = 0;
}

La ejecución de la secuencia de comandos anterior devuelve una salida similar al siguiente ejemplo:


# dtrace -s ./where.d
dtrace: script './where.d' matched 5 probes
^C

        0
           value  ------------- Distribution ------------- count    
            2048 |                                         0        
            4096 |@@                                       37       
            8192 |@@@@@@@@@@@@@                            212      
           16384 |@                                        30       
           32768 |                                         10       
           65536 |@                                        17       
          131072 |                                         12       
          262144 |                                         9        
          524288 |                                         6        
         1048576 |                                         5        
         2097152 |                                         1        
         4194304 |                                         3        
         8388608 |@@@@                                     75       
        16777216 |@@@@@@@@@@@@                             201      
        33554432 |                                         6        
        67108864 |                                         0        

        1
           value  ------------- Distribution ------------- count    
            2048 |                                         0        
            4096 |@                                        6        
            8192 |@@@@                                     23       
           16384 |@@@                                      18       
           32768 |@@@@                                     22       
           65536 |@@@@                                     22       
          131072 |@                                        7        
          262144 |                                         5        
          524288 |                                         2        
         1048576 |                                         3        
         2097152 |@                                        9        
         4194304 |                                         4        
         8388608 |@@@                                      18       
        16777216 |@@@                                      19       
        33554432 |@@@                                      16       
        67108864 |@@@@                                     21       
       134217728 |@@                                       14       
       268435456 |                                         0

La salida anterior muestra que los subprocesos de la CPU 1 tienden a ejecutarse por menos de 100 microsegundos seguidos, o durante aproximadamente 10 milisegundos. En el histograma se muestra una importante diferencia entre los dos clústeres de datos. Podría estar también interesado en saber qué CPU están ejecutando un proceso determinado. También puede utilizar los sondeos on-cpu y off-cpu para responder a esta cuestión. La siguiente secuencia de comandos muestra qué CPU ejecutan una aplicación determinada durante un periodo de 10 segundos:

#pragma D option quiet

dtrace:::BEGIN
{
	start = timestamp;
}

sched:::on-cpu
/execname == $$1/
{
	self->ts = timestamp;
}

sched:::off-cpu
/self->ts/
{
	@[cpu] = sum(timestamp - self->ts);
	self->ts = 0;
}

profile:::tick-1sec
/++x == 10/
{
	exit(0);
}
        
dtrace:::END
{
	printf("CPU distribution of imapd over %d seconds:\n\n",
	    (timestamp - start) / 1000000000);
	printf("CPU microseconds\n--- ------------\n");
	normalize(@, 1000);
	printa("%3d %@d\n", @);
}

Ejecutando la secuencia de comandos anterior en un gran servidor de correo y especificando el daemon IMAP, devuelve una salida similar al ejemplo siguiente:


# dtrace -s ./whererun.d imapd
CPU distribution of imapd over 10 seconds:

CPU microseconds
--- ------------
 15 10102
 12 16377
 21 25317
 19 25504
 17 35653
 13 41539
 14 46669
 20 57753
 22 70088
 16 115860
 23 127775
 18 160517

Solaris tiene en cuenta el tiempo que ha estado un subproceso en inactividad a la hora de seleccionar la CPU en la que ejecutar el subproceso: un subproceso que ha estado en actividad durante menos tiempo tiende a no migrar. Puede utilizar los sondeos off-cpu y on-cpu para observar esta conducta:

sched:::off-cpu
/curlwpsinfo->pr_state == SSLEEP/
{
	self->cpu = cpu;
	self->ts = timestamp;
}

sched:::on-cpu
/self->ts/
{
	@[self->cpu == cpu ?
	    "sleep time, no CPU migration" : "sleep time, CPU migration"] =
	    lquantize((timestamp - self->ts) / 1000000, 0, 500, 25);
	self->ts = 0;
	self->cpu = 0;
}

La ejecución de la secuencia de comandos anterior durante aproximadamente 30 segundos devuelve una salida similar al siguiente ejemplo:


# dtrace -s ./howlong.d
dtrace: script './howlong.d' matched 5 probes
^C
 sleep time, CPU migration                         
           value  -------------- Distribution ------------ count    
             < 0 |                                         0        
               0 |@@@@@@@                                  6838     
              25 |@@@@@                                    4714     
              50 |@@@                                      3108     
              75 |@                                        1304     
             100 |@                                        1557     
             125 |@                                        1425     
             150 |                                         894      
             175 |@                                        1526     
             200 |@@                                       2010     
             225 |@@                                       1933     
             250 |@@                                       1982     
             275 |@@                                       2051     
             300 |@@                                       2021     
             325 |@                                        1708     
             350 |@                                        1113     
             375 |                                         502      
             400 |                                         220      
             425 |                                         106      
             450 |                                         54       
             475 |                                         40       
          >= 500 |@                                        1716     

  sleep time, no CPU migration                      
           value  -------------- Distribution ------------ count    
             < 0 |                                         0        
               0 |@@@@@@@@@@@@                             58413    
              25 |@@@                                      14793    
              50 |@@                                       10050    
              75 |                                         3858     
             100 |@                                        6242     
             125 |@                                        6555     
             150 |                                         3980     
             175 |@                                        5987     
             200 |@                                        9024     
             225 |@                                        9070     
             250 |@@                                       10745    
             275 |@@                                       11898    
             300 |@@                                       11704    
             325 |@@                                       10846    
             350 |@                                        6962     
             375 |                                         3292     
             400 |                                         1713     
             425 |                                         585      
             450 |                                         201      
             475 |                                         96       
          >= 500 |                                         3946

La salida de ejemplo muestra que hay más ocurrencias de no migración que de migración. Asimismo, cuando los tiempos de inactividad son mayores, la posibilidad de migración es más alta. Las distribuciones son notablemente diferentes en el intervalo inferior a los 100 milisegundos, pero su apariencia es muy similar a medida que aumentan los tiempos de inactividad. Este resultado parecería indicar que el tiempo de inactividad no es un factor decisivo en la planificación una vez que se supera un umbral determinado.

El ejemplo final que utiliza off-cpu y on-cpu muestra cómo utilizar estos sondeos junto con el campo pr_stype para determinar por qué los subprocesos se encuentran en inactividad y durante cuánto tiempo:

sched:::off-cpu
/curlwpsinfo->pr_state == SSLEEP/
{
	/*
	 * We're sleeping.  Track our sobj type.
	 */
	self->sobj = curlwpsinfo->pr_stype;
	self->bedtime = timestamp;
}

sched:::off-cpu
/curlwpsinfo->pr_state == SRUN/
{
	self->bedtime = timestamp;
}

sched:::on-cpu
/self->bedtime && !self->sobj/
{
	@["preempted"] = quantize(timestamp - self->bedtime);
	self->bedtime = 0;
}

sched:::on-cpu
/self->sobj/
{
	@[self->sobj == SOBJ_MUTEX ? "kernel-level lock" :
	    self->sobj == SOBJ_RWLOCK ? "rwlock" :
	    self->sobj == SOBJ_CV ? "condition variable" :
	    self->sobj == SOBJ_SEMA ? "semaphore" :
	    self->sobj == SOBJ_USER ? "user-level lock" :
	    self->sobj == SOBJ_USER_PI ? "user-level prio-inheriting lock" :
	    self->sobj == SOBJ_SHUTTLE ? "shuttle" : "unknown"] =
	    quantize(timestamp - self->bedtime);

	self->sobj = 0;
	self->bedtime = 0;
}

La ejecución de la secuencia de comandos anterior durante varios segundos devuelve una salida similar al siguiente ejemplo:


# dtrace -s ./whatfor.d
dtrace: script './whatfor.d' matched 12 probes
^C
 kernel-level lock
           value  -------------- Distribution ------------ count    
           16384 |                                         0        
           32768 |@@@@@@@@                                 3        
           65536 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@            11       
          131072 |@@                                       1        
          262144 |                                         0        

  preempted
           value  -------------- Distribution ------------ count    
           16384 |                                         0        
           32768 |                                         4        
           65536 |@@@@@@@@                                 408      
          131072 |@@@@@@@@@@@@@@@@@@@@@@                   1031     
          262144 |@@@                                      156      
          524288 |@@                                       116      
         1048576 |@                                        51       
         2097152 |                                         42       
         4194304 |                                         16       
         8388608 |                                         15       
        16777216 |                                         4        
        33554432 |                                         8        
        67108864 |                                         0        

  semaphore
           value  -------------- Distribution ------------ count    
           32768 |                                         0        
           65536 |@@                                       61       
          131072 |@@@@@@@@@@@@@@@@@@@@@@@@                 553      
          262144 |@@                                       63       
          524288 |@                                        36       
         1048576 |                                         7        
         2097152 |                                         22       
         4194304 |@                                        44       
         8388608 |@@@                                      84       
        16777216 |@                                        36       
        33554432 |                                         3        
        67108864 |                                         6        
       134217728 |                                         0        
       268435456 |                                         0        
       536870912 |                                         0        
      1073741824 |                                         0        
      2147483648 |                                         0        
      4294967296 |                                         0        
      8589934592 |                                         0        
     17179869184 |                                         1        
     34359738368 |                                         0        

  shuttle                                           
           value  -------------- Distribution ------------ count    
           32768 |                                         0        
           65536 |@@@@@                                    2        
          131072 |@@@@@@@@@@@@@@@@                         6        
          262144 |@@@@@                                    2        
          524288 |                                         0        
         1048576 |                                         0        
         2097152 |                                         0        
         4194304 |@@@@@                                    2        
         8388608 |                                         0        
        16777216 |                                         0        
        33554432 |                                         0        
        67108864 |                                         0        
       134217728 |                                         0        
       268435456 |                                         0        
       536870912 |                                         0        
      1073741824 |                                         0        
      2147483648 |                                         0        
      4294967296 |@@@@@                                    2        
      8589934592 |                                         0        
     17179869184 |@@                                       1        
     34359738368 |                                         0        

  condition variable                                
           value  -------------- Distribution ------------ count    
           32768 |                                         0        
           65536 |                                         122      
          131072 |@@@@@                                    1579     
          262144 |@                                        340      
          524288 |                                         268      
         1048576 |@@@                                      1028     
         2097152 |@@@                                      1007     
         4194304 |@@@                                      1176     
         8388608 |@@@@                                     1257     
        16777216 |@@@@@@@@@@@@@@                           4385     
        33554432 |                                         295      
        67108864 |                                         157      
       134217728 |                                         96       
       268435456 |                                         48       
       536870912 |                                         144      
      1073741824 |                                         10       
      2147483648 |                                         22       
      4294967296 |                                         18       
      8589934592 |                                         5        
     17179869184 |                                         6        
     34359738368 |                                         4        
     68719476736 |                                         0

enqueue y dequeue

Cuando una CPU pasa a estado de inactividad, el distribuidor busca trabajos en cola en otras CPU (que no se encuentran en inactividad). El siguiente ejemplo utiliza el sondeo dequeue para comprender la frecuencia con la que se transfieren las aplicaciones y qué CPU lo hace:

#pragma D option quiet

sched:::dequeue
/args[2]->cpu_id != --1 && cpu != args[2]->cpu_id &&
    (curlwpsinfo->pr_flag & PR_IDLE)/
{
	@[stringof(args[1]->pr_fname), args[2]->cpu_id] =
	    lquantize(cpu, 0, 100);
}

END
{
	printa("%s stolen from CPU %d by:\n%@d\n", @);
}

La cola de la salida de la ejecución de la secuencia de comandos anterior en un sistema con 4 CPU devuelve una salida similar al siguiente ejemplo:


# dtrace -s ./whosteal.d
^C
...
 nscd stolen from CPU 1 by:

           value  -------------- Distribution ------------ count    
               1 |                                         0        
               2 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 28       
               3 |                                         0        

snmpd stolen from CPU 1 by:

           value  -------------- Distribution ------------ count    
             < 0 |                                         0        
               0 |@                                        1        
               1 |                                         0        
               2 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@     31       
               3 |@@                                       2        
               4 |                                         0        

sched stolen from CPU 1 by:

           value  -------------- Distribution ------------ count    
             < 0 |                                         0        
               0 |@@                                       3        
               1 |                                         0        
               2 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@         36       
               3 |@@@@                                     5        
               4 |                                         0

En lugar de saber qué CPU realizó qué trabajo, puede que desee conocer las CPU en las que los procesos y subprocesos están esperando a ejecutarse. Puede utilizar los sondeos enqueue y dequeue de forma conjunta para resolver esta duda:

sched:::enqueue
{
	self->ts = timestamp;
}

sched:::dequeue
/self->ts/
{
	@[args[2]->cpu_id] = quantize(timestamp - self->ts);
	self->ts = 0;
}

La ejecución de la secuencia de comandos anterior durante varios segundos devuelve una salida similar al siguiente ejemplo:


# dtrace -s ./qtime.d
dtrace: script './qtime.d' matched 5 probes
^C
       -1
           value  -------------- Distribution ------------ count    
            4096 |                                         0        
            8192 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 2        
           16384 |                                         0        

        0
           value  -------------- Distribution ------------ count    
            1024 |                                         0        
            2048 |@@@@@@@@@@@@@@@                          262      
            4096 |@@@@@@@@@@@@@                            227      
            8192 |@@@@@                                    87       
           16384 |@@@                                      54       
           32768 |                                         7        
           65536 |                                         9        
          131072 |                                         1        
          262144 |                                         5        
          524288 |                                         4        
         1048576 |                                         2        
         2097152 |                                         0        
         4194304 |                                         0        
         8388608 |                                         0        
        16777216 |                                         1        
        33554432 |                                         2        
        67108864 |                                         2        
       134217728 |                                         0        
       268435456 |                                         0        
       536870912 |                                         0        
      1073741824 |                                         1        
      2147483648 |                                         1        
      4294967296 |                                         0        

        1
           value  -------------- Distribution ------------ count    
            1024 |                                         0        
            2048 |@@@@                                     49       
            4096 |@@@@@@@@@@@@@@@@@@@@                     241      
            8192 |@@@@@@@                                  91       
           16384 |@@@@                                     55       
           32768 |                                         7        
           65536 |                                         3        
          131072 |                                         2        
          262144 |                                         1        
          524288 |                                         0        
         1048576 |                                         0        
         2097152 |                                         0        
         4194304 |                                         0        
         8388608 |                                         0        
        16777216 |                                         0        
        33554432 |                                         3        
        67108864 |                                         1        
       134217728 |                                         4        
       268435456 |                                         2        
       536870912 |                                         0        
      1073741824 |                                         3        
      2147483648 |                                         2        
      4294967296 |                                         0

Observe los valores que no son cero al final de la salida de ejemplo. Estos puntos de datos revelan diversas instancias en ambas CPU en las que se situó en cola un subproceso para que se ejecutara durante varios segundos.

En lugar de observar los tiempos de espera, puede que desee examinar la longitud de la cola de ejecución a través del tiempo. Mediante los sondeos enqueue y dequeue puede establecer una matriz asociativa para que realice un seguimiento de la longitud de la cola:

sched:::enqueue
{
	this->len = qlen[args[2]->cpu_id]++;
	@[args[2]->cpu_id] = lquantize(this->len, 0, 100);
}

sched:::dequeue
/qlen[args[2]->cpu_id]/
{
	qlen[args[2]->cpu_id]—;
}

La ejecución de la secuencia de comandos anterior durante aproximadamente 30 segundos en un sistema portátil monoprocesador con un amplio tiempo de inactividad devolvería una salida similar a la del siguiente ejemplo:


# dtrace -s ./qlen.d
dtrace: script './qlen.d' matched 5 probes
^C
        0
           value  -------------- Distribution ------------ count    
             < 0 |                                         0        
               0 |@@@@@@@@@@@@@@@@@@@@@@@@@                110626   
               1 |@@@@@@@@@                                41142    
               2 |@@                                       12655    
               3 |@                                        5074     
               4 |                                         1722     
               5 |                                         701      
               6 |                                         302      
               7 |                                         63       
               8 |                                         23       
               9 |                                         12       
              10 |                                         24       
              11 |                                         58       
              12 |                                         14       
              13 |                                         3        
              14 |                                         0

La salida es básicamente lo que cabría esperar de un sistema en inactividad: la mayor parte del tiempo durante la que se sitúa en cola un subproceso ejecutable, el tamaño de la cola de ejecución era escaso (longitud de tres subprocesos o inferior). Sin embargo, dado que el sistema estuvo en inactividad durante un largo periodo de tiempo, los puntos de datos de la parte inferior de la tabla podrían ser inesperados. Por ejemplo, ¿por qué tenía la cola de ejecución 13 subprocesos ejecutables? Para explorar esta cuestión, podría escribir una secuencia de comandos D que muestre el contenido de la cola de ejecución cuando su longitud sea amplia. Este problema es complicado, dado que la habilitación de D no puede iterar a lo largo de estructuras de datos y, por lo tanto, no puede simplemente iterar a través de toda la cola de ejecución. Incluso si la habilitación de D pudiera hacerlo, debería evitar dependencias con las estructuras de datos internas del núcleo.

Para este tipo de secuencia de comandos, habilitará los sondeos enqueue y dequeue y utilizaría tanto especulaciones como matrices asociativas. Siempre que se sitúa en cola un subproceso, la secuencia de comandos aumenta la longitud de la cola, y registra la marca de hora en una matriz asociativa grabada por el subproceso. En este caso no podrá utilizar una variable thread-local, ya que un subproceso podría situar en cola a otro. La secuencia de comandos comprueba si la longitud de la cola supera el máximo. En caso afirmativo, inicia una nueva especulación y registra la marca horaria y el nuevo máximo. Posteriormente, cuando se quita de cola un subproceso, la secuencia de comandos compara la marca horaria en cola con la marca horaria de mayor longitud: si el proceso se colocó en cola antes que la marca horaria de mayor longitud, el subproceso se encontraba en cola al registrar el subproceso de mayor longitud. En este caso, la secuencia de comandos realiza un seguimiento de forma especulativa de la información del subproceso. Una vez que el núcleo quita de la cola el último subproceso que se encontraba en cola en la marca horaria de mayor longitud, la secuencia de comandos efectúa los datos de especulación. Esta secuencia de comandos se muestra a continuación:

#pragma D option quiet
#pragma D option nspec=4
#pragma D option specsize=100k

int maxlen;
int spec[int];

sched:::enqueue
{
	this->len = ++qlen[this->cpu = args[2]->cpu_id];
	in[args[0]->pr_addr] = timestamp;
}

sched:::enqueue
/this->len > maxlen && spec[this->cpu]/
{
	/*
	 * There is already a speculation for this CPU.  We just set a new
	 * record, so we'll discard the old one.
	 */
	discard(spec[this->cpu]);
}

sched:::enqueue
/this->len > maxlen/
{
	/*
	 * We have a winner.  Set the new maximum length and set the timestamp
	 * of the longest length.
	 */
	maxlen = this->len;
	longtime[this->cpu] = timestamp;	

	/*
	 * Now start a new speculation, and speculatively trace the length.
	 */
	this->spec = spec[this->cpu] = speculation();
	speculate(this->spec);
	printf("Run queue of length %d:\n", this->len);
}

sched:::dequeue
/(this->in = in[args[0]->pr_addr]) &&
    this->in <= longtime[this->cpu = args[2]->cpu_id]/
{
	speculate(spec[this->cpu]);
	printf("  %d/%d (%s)\n", 
	    args[1]->pr_pid, args[0]->pr_lwpid,
	    stringof(args[1]->pr_fname));
}

sched:::dequeue
/qlen[args[2]->cpu_id]/
{
	in[args[0]->pr_addr] = 0;
	this->len = --qlen[args[2]->cpu_id];
}

sched:::dequeue
/this->len == 0 && spec[this->cpu]/
{
	/*
	 * We just processed the last thread that was enqueued at the time
	 * of longest length; commit the speculation, which by now contains
	 * each thread that was enqueued when the queue was longest.
	 */
	commit(spec[this->cpu]);
	spec[this->cpu] = 0;
}

La ejecución de la secuencia de comandos anterior en el mismo portátil monoprocesador devuelve una salida similar a la del siguiente ejemplo:


# dtrace -s ./whoqueue.d
Run queue of length 3:
 0/0 (sched)
  0/0 (sched)
  101170/1 (dtrace)
Run queue of length 4:
  0/0 (sched)
  100356/1 (Xsun)
  100420/1 (xterm)
  101170/1 (dtrace)
Run queue of length 5:
  0/0 (sched)
  0/0 (sched)
  100356/1 (Xsun)
  100420/1 (xterm)
  101170/1 (dtrace)
Run queue of length 7:
  0/0 (sched)
  100221/18 (nscd)
  100221/17 (nscd)
  100221/16 (nscd)
  100221/13 (nscd)
  100221/14 (nscd)
  100221/15 (nscd)
Run queue of length 16:
  100821/1 (xterm)
  100768/1 (xterm)
  100365/1 (fvwm2)
  101118/1 (xterm)
  100577/1 (xterm)
  101170/1 (dtrace)
  101020/1 (xterm)
  101089/1 (xterm)
  100795/1 (xterm)
  100741/1 (xterm)
  100710/1 (xterm)
  101048/1 (xterm)
  100697/1 (MozillaFirebird-)
  100420/1 (xterm)
  100394/1 (xterm)
  100368/1 (xterm)
^C

La salida revela que las largas colas de ejecución están motivadas por un alto número de procesos xterm no ejecutables. Este experimento coincidía con un cambio en el escritorio virtual y, por lo tanto, los resultados probablemente están provocados por algún tipo de procesamiento de evento X.

sleep y wakeup

En enqueue y dequeue, el ejemplo final demuestra que la ráfaga en la longitud de la cola de ejecución está motivada por procesos xterm. Una hipótesis es que las observaciones estuvieron provocadas por un cambio en el escritorio virtual. Es posible utilizar el sondeo wakeup para explorar esta hipótesis determinando quién y cuándo está activando los procesos xterm, tal y como se muestra en el ejemplo siguiente:

#pragma D option quiet

dtrace:::BEGIN
{
	start = timestamp;
}

sched:::wakeup
/stringof(args[1]->pr_fname) == "xterm"/
{
	@[execname] = lquantize((timestamp - start) / 1000000000, 0, 10);
}

profile:::tick-1sec
/++x == 10/
{
	exit(0);
}

Para investigar la hipótesis, ejecute la secuencia de comandos anterior, esperando unos cinco segundos, y cambie el escritorio virtual una única vez. Si la ráfaga de procesos no ejecutables xterm está motivada por un cambio de escritorio virtual, la salida debería mostrar una ráfaga de actividad de activación en la marca de cinco segundos.


# dtrace -s ./xterm.d

  Xsun

           value  -------------- Distribution ------------ count    
               4 |                                         0        
               5 |@                                        1        
               6 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   32       
               7 |                                         0

La salida muestra que el servidor X está activando procesos xterm, agrupados en torno al momento en el que cambiaron los escritorios virtuales. Si su intención era comprender la interacción entre el servidor X y los procesos xterm, podrá agregar en la pila de usuario marcas de seguimiento cuando el servidor X active el sondeo wakeup.

La comprensión del rendimiento de sistemas cliente/servidor tales como el sistema de ventanas X requiere comprender a los clientes en nombre de los cuales está realizando el trabajo el servidor. Este tipo de pregunta es difícil de responder con herramientas convencionales de análisis de rendimiento. Sin embargo, si cuenta con un modelo en el que un cliente envía un mensaje al servidor y pasa a inactividad esperando el procesamiento por parte del servidor, podría utilizar el sondeo wakeup para determinar el cliente para el que se está realizando la solicitud, tal y como se muestra en el siguiente ejemplo:

self int last;

sched:::wakeup
/self->last && args[0]->pr_stype == SOBJ_CV/
{
	@[stringof(args[1]->pr_fname)] = sum(vtimestamp - self->last);
	self->last = 0;
}

sched:::wakeup
/execname == "Xsun" && self->last == 0/
{
	self->last = vtimestamp;
}

La ejecución de la secuencia de comandos anterior devuelve una salida similar al siguiente ejemplo:


dtrace -s ./xwork.d
dtrace: script './xwork.d' matched 14 probes
^C
  xterm                                                       9522510
  soffice.bin                                                 9912594
  fvwm2                                                     100423123
  MozillaFirebird                                           312227077
  acroread                                                  345901577

Esta salida revela que gran parte del trabajo Xsun se está realizando en nombre de los procesos acroread, MozillaFirebird y, en menor grado, fvwm2. Tenga en cuenta que la secuencia de comandos sólo examinó activaciones desde objetos de sincronización de variables de condición (SOBJ_CV). Tal y como se describe en la Tabla 25–4las variables de condición son el tipo de objeto de sincronización que suele utilizarse para sincronizar por razones diferentes al acceso a una región de datos compartida. En el caso del servidor X, un cliente esperará los datos en un sector de conducción esperando en inactividad en una variable de condición.

Asimismo, puede utilizar el sondeo sleep junto con el sondeo wakeup para saber qué aplicaciones están bloqueando en qué aplicaciones y durante cuánto tiempo, tal y como se muestra en el siguiente ejemplo:

#pragma D option quiet

sched:::sleep
/!(curlwpsinfo->pr_flag & PR_ISSYS) && curlwpsinfo->pr_stype == SOBJ_CV/
{
	bedtime[curlwpsinfo->pr_addr] = timestamp;
}

sched:::wakeup
/bedtime[args[0]->pr_addr]/
{
	@[stringof(args[1]->pr_fname), execname] =
	    quantize(timestamp - bedtime[args[0]->pr_addr]);
	bedtime[args[0]->pr_addr] = 0;
}

END
{
	printa("%s sleeping on %s:\n%@d\n", @);
}

La cola de la salida resultante de la ejecución de la secuencia de comandos de ejemplo durante varios segundos en un sistema de escritorio es similar al siguiente ejemplo:


# dtrace -s ./whofor.d
^C
...
 xterm sleeping on Xsun:

           value  -------------- Distribution ------------ count    
          131072 |                                         0        
          262144 |                                         12       
          524288 |                                         2        
         1048576 |                                         0        
         2097152 |                                         5        
         4194304 |@@@                                      45       
         8388608 |                                         1        
        16777216 |                                         9        
        33554432 |@@@@@                                    83       
        67108864 |@@@@@@@@@@@                              164      
       134217728 |@@@@@@@@@@                               147      
       268435456 |@@@@                                     56       
       536870912 |@                                        17       
      1073741824 |                                         9        
      2147483648 |                                         1        
      4294967296 |                                         3        
      8589934592 |                                         1        
     17179869184 |                                         0        

fvwm2 sleeping on Xsun:

           value  -------------- Distribution ------------ count    
           32768 |                                         0        
           65536 |@@@@@@@@@@@@@@@@@@@@@@                   67       
          131072 |@@@@@                                    16       
          262144 |@@                                       6        
          524288 |@                                        3        
         1048576 |@@@@@                                    15       
         2097152 |                                         0        
         4194304 |                                         0        
         8388608 |                                         1        
        16777216 |                                         0        
        33554432 |                                         0        
        67108864 |                                         1        
       134217728 |                                         0        
       268435456 |                                         0        
       536870912 |                                         1        
      1073741824 |                                         1        
      2147483648 |                                         2        
      4294967296 |                                         2        
      8589934592 |                                         2        
     17179869184 |                                         0        
     34359738368 |                                         2        
     68719476736 |                                         0        

syslogd sleeping on syslogd:

           value  -------------- Distribution ------------ count    
     17179869184 |                                         0        
     34359738368 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 3        
     68719476736 |                                         0        

MozillaFirebird sleeping on MozillaFirebird:

           value  -------------- Distribution ------------ count    
           65536 |                                         0        
          131072 |                                         3        
          262144 |@@                                       14       
          524288 |                                         0        
         1048576 |@@@                                      18       
         2097152 |                                         0        
         4194304 |                                         0        
         8388608 |                                         1        
        16777216 |                                         0        
        33554432 |                                         1        
        67108864 |                                         3        
       134217728 |@                                        7        
       268435456 |@@@@@@@@@@                               53       
       536870912 |@@@@@@@@@@@@@@                           78       
      1073741824 |@@@@                                     25       
      2147483648 |                                         0        
      4294967296 |                                         0        
      8589934592 |@                                        7        
     17179869184 |                                         0

Puede que desee comprender cómo y por qué razón MozillaFirebird se está bloqueando a sí mismo. Puede modificar la secuencia de comandos anterior del siguiente modo para responder a esta pregunta:

#pragma D option quiet

sched:::sleep
/execname == "MozillaFirebird" && curlwpsinfo->pr_stype == SOBJ_CV/
{
	bedtime[curlwpsinfo->pr_addr] = timestamp;
}

sched:::wakeup
/execname == "MozillaFirebird" && bedtime[args[0]->pr_addr]/
{
	@[args[1]->pr_pid, args[0]->pr_lwpid, pid, curlwpsinfo->pr_lwpid] = 
	    quantize(timestamp - bedtime[args[0]->pr_addr]);
	bedtime[args[0]->pr_addr] = 0;
}

sched:::wakeup
/bedtime[args[0]->pr_addr]/
{
	bedtime[args[0]->pr_addr] = 0;
}

END
{
	printa("%d/%d sleeping on %d/%d:\n%@d\n", @);
}

La ejecución de la secuencia de comandos modificada durante varios segundos devolverá una salida similar a la del siguiente ejemplo:


# dtrace -s ./firebird.d
^C

 100459/1 sleeping on 100459/13:

           value  -------------- Distribution ------------ count    
          262144 |                                         0        
          524288 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1        
         1048576 |                                         0        

100459/13 sleeping on 100459/1:

           value  -------------- Distribution ------------ count    
        16777216 |                                         0        
        33554432 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1        
        67108864 |                                         0        

100459/1 sleeping on 100459/2:

           value  -------------- Distribution ------------ count    
           16384 |                                         0        
           32768 |@@@@                                     5        
           65536 |@                                        2        
          131072 |@@@@@                                    6        
          262144 |                                         1        
          524288 |@                                        2        
         1048576 |                                         0        
         2097152 |@@                                       3        
         4194304 |@@@@                                     5        
         8388608 |@@@@@@@@                                 9        
        16777216 |@@@@@                                    6        
        33554432 |@@                                       3        
        67108864 |                                         0        

100459/1 sleeping on 100459/5:

           value  -------------- Distribution ------------ count    
           16384 |                                         0        
           32768 |@@@@@                                    12       
           65536 |@@                                       5        
          131072 |@@@@@@                                   15       
          262144 |                                         1        
          524288 |                                         1        
         1048576 |                                         2        
         2097152 |@                                        4        
         4194304 |@@@@@                                    13       
         8388608 |@@@                                      8        
        16777216 |@@@@@                                    13       
        33554432 |@@                                       6        
        67108864 |@@                                       5        
       134217728 |@                                        4        
       268435456 |                                         0        
       536870912 |                                         1        
      1073741824 |                                         0        

100459/2 sleeping on 100459/1:

           value  -------------- Distribution ------------ count    
           16384 |                                         0        
           32768 |@@@@@@@@@@@@@@                           11       
           65536 |                                         0        
          131072 |@@                                       2        
          262144 |                                         0        
          524288 |                                         0        
         1048576 |@@@@                                     3        
         2097152 |@                                        1        
         4194304 |@@                                       2        
         8388608 |@@                                       2        
        16777216 |@                                        1        
        33554432 |@@@@@@                                   5        
        67108864 |                                         0        
       134217728 |                                         0        
       268435456 |                                         0        
       536870912 |@                                        1        
      1073741824 |@                                        1        
      2147483648 |@                                        1        
      4294967296 |                                         0        

100459/5 sleeping on 100459/1:

           value  -------------- Distribution ------------ count    
           16384 |                                         0        
           32768 |                                         1        
           65536 |                                         2        
          131072 |                                         4        
          262144 |                                         7        
          524288 |                                         1        
         1048576 |                                         5        
         2097152 |                                         10       
         4194304 |@@@@@@                                   77       
         8388608 |@@@@@@@@@@@@@@@@@@@@@@@                  270      
        16777216 |@@@                                      43       
        33554432 |@                                        20       
        67108864 |@                                        14       
       134217728 |                                         5        
       268435456 |                                         2        
       536870912 |                                         1        
      1073741824 |                                         0        

Puede utilizar también los sondeos sleep y wakeup para comprender el rendimiento de servidores puerta, como el daemon name service cache, tal y como se muestra en el siguiente ejemplo:

sched:::sleep
/curlwpsinfo->pr_stype == SOBJ_SHUTTLE/
{
	bedtime[curlwpsinfo->pr_addr] = timestamp;
}

sched:::wakeup
/execname == "nscd" && bedtime[args[0]->pr_addr]/
{
	@[stringof(curpsinfo->pr_fname), stringof(args[1]->pr_fname)] =
	    quantize(timestamp - bedtime[args[0]->pr_addr]);
	bedtime[args[0]->pr_addr] = 0;
}

sched:::wakeup
/bedtime[args[0]->pr_addr]/
{
	bedtime[args[0]->pr_addr] = 0;
}

La cola de la salida al ejecutar la secuencia de comandos anterior en un gran servidor de correo es similar al siguiente ejemplo:


imapd
           value  -------------- Distribution ------------ count    
           16384 |                                         0        
           32768 |                                         2        
           65536 |@@@@@@@@@@@@@@@@@                        57       
          131072 |@@@@@@@@@@@                              37       
          262144 |                                         3        
          524288 |@@@                                      11       
         1048576 |@@@                                      10       
         2097152 |@@                                       9        
         4194304 |                                         1        
         8388608 |                                         0        

  mountd                                            
           value  -------------- Distribution ------------ count    
           65536 |                                         0        
          131072 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@            49       
          262144 |@@@                                      6        
          524288 |                                         1        
         1048576 |                                         0        
         2097152 |                                         0        
         4194304 |@@@@                                     7        
         8388608 |@                                        3        
        16777216 |                                         0        

  sendmail
           value  -------------- Distribution ------------ count    
           16384 |                                         0        
           32768 |@                                        18       
           65536 |@@@@@@@@@@@@@@@@@                        205      
          131072 |@@@@@@@@@@@@@                            154      
          262144 |@                                        23       
          524288 |                                         5        
         1048576 |@@@@                                     50       
         2097152 |                                         7        
         4194304 |                                         5        
         8388608 |                                         2        
        16777216 |                                         0        

  automountd                                        
           value  -------------- Distribution ------------ count    
           32768 |                                         0        
           65536 |@@@@@@@@@@                               22       
          131072 |@@@@@@@@@@@@@@@@@@@@@@@                  51       
          262144 |@@                                       6        
          524288 |                                         1        
         1048576 |                                         0        
         2097152 |                                         2        
         4194304 |                                         2        
         8388608 |                                         1        
        16777216 |                                         1        
        33554432 |                                         1        
        67108864 |                                         0        
       134217728 |                                         0        
       268435456 |                                         1        
       536870912 |                                         0

Podría estar interesado en los inusuales puntos de datos para automountd o en el punto de datos persistente a más de un milisegundo para sendmail. Asimismo, puede añadir predicados a la secuencia de comandos anterior para conocer detalladamente las causas de cualquier tipo de resultado excepcional o anómalo.

preempt, remain-cpu

Dado que Solaris es un sistema preemptivo, los subprocesos de mayor prioridad se adelantan a los de una prioridad más baja. La preempción puede provocar una burbuja de latencia significativa en el subproceso de menor prioridad, por lo que puede que desee saber qué subprocesos están adelantándose a cuáles. El siguiente ejemplo muestra cómo utilizar los sondeos preempt y remain-cpu para visualizar esta información:

#pragma D option quiet

sched:::preempt
{
	self->preempt = 1;
}

sched:::remain-cpu
/self->preempt/
{
	self->preempt = 0;
}

sched:::off-cpu
/self->preempt/
{
	/*
	 * If we were told to preempt ourselves, see who we ended up giving
	 * the CPU to.
	 */
	@[stringof(args[1]->pr_fname), args[0]->pr_pri, execname,
	    curlwpsinfo->pr_pri] = count();
	self->preempt = 0;
}

END
{
	printf("%30s %3s %30s %3s %5s\n", "PREEMPTOR", "PRI",
	    "PREEMPTED", "PRI", "#");
	printa("%30s %3d %30s %3d %5@d\n", @);
}

La ejecución de la secuencia de comandos anterior en un sistema de escritorio devuelve una salida similar a la mostrada en el siguiente ejemplo:


# dtrace -s ./whopreempt.d
^C
                     PREEMPTOR PRI                      PREEMPTED PRI     #
                         sched  60                           Xsun  53     1
                         xterm  59                           Xsun  53     1
               MozillaFirebird  57                           Xsun  53     1
                        mpstat 100                          fvwm2  59     1
                         sched  99                MozillaFirebird  57     1
                         sched  60                         dtrace  30     1
                        mpstat 100                           Xsun  59     2
                         sched  60                           Xsun  54     2
                         sched  99                          sched  60     2
                         fvwm2  59                           Xsun  44     2
                         sched  99                           Xsun  44     2
                         sched  60                          xterm  59     2
                         sched  99                           Xsun  53     2
                         sched  99                           Xsun  54     3
                         sched  60                          fvwm2  59     3
                         sched  60                           Xsun  59     3
                         sched  99                           Xsun  59     4
                         fvwm2  59                           Xsun  54     8
                         fvwm2  59                           Xsun  53     9
                          Xsun  59                MozillaFirebird  57    10
                         sched  60                MozillaFirebird  57    14
               MozillaFirebird  57                           Xsun  44    16
               MozillaFirebird  57                           Xsun  54    18

change-pri

La preempción se basa en las prioridades, por lo que puede que desee observar los cambios de prioridad durante un periodo de tiempo. El siguiente ejemplo utiliza el sondeo change-pri para visualizar esta información:

sched:::change-pri
{
	@[stringof(args[0]->pr_clname)] =
	    lquantize(args[2] - args[0]->pr_pri, -50, 50, 5);
}

La secuencia de comandos de ejemplo captura el grado de aumento o disminución de la prioridad, y realiza adiciones según la clase de planificación. La ejecución de la secuencia de comandos anterior devuelve una salida similar al siguiente ejemplo:


# dtrace -s ./pri.d
dtrace: script './pri.d' matched 10 probes
^C
 IA                                                
           value  -------------- Distribution ------------ count    
           < -50 |                                         20       
             -50 |@                                        38       
             -45 |                                         4        
             -40 |                                         13       
             -35 |                                         12       
             -30 |                                         18       
             -25 |                                         18       
             -20 |                                         23       
             -15 |                                         6        
             -10 |@@@@@@@@                                 201      
              -5 |@@@@@@                                   160      
               0 |@@@@@                                    138      
               5 |@                                        47       
              10 |@@                                       66       
              15 |@                                        36       
              20 |@                                        26       
              25 |@                                        28       
              30 |                                         18       
              35 |                                         22       
              40 |                                         8        
              45 |                                         11       
           >= 50 |@                                        34       

  TS                                                
           value  -------------- Distribution ------------ count    
             -15 |                                         0        
             -10 |@                                        1        
              -5 |@@@@@@@@@@@@                             7        
               0 |@@@@@@@@@@@@@@@@@@@@                     12       
               5 |                                         0        
              10 |@@@@@                                    3        
              15 |                                         0

El resultado muestra la manipulación de prioridad de la clase de planificación Interactive (IA). En lugar de percibir la manipulación de la prioridad, quizá desee ver los valores de prioridad de un proceso y subproceso determinado a lo largo del tiempo. La siguiente secuencia de comandos utiliza el sondeo change-pri para visualizar esta información:

#pragma D option quiet

BEGIN
{
	start = timestamp;
}

sched:::change-pri
/args[1]->pr_pid == $1 && args[0]->pr_lwpid == $2/
{
	printf("%d %d\n", timestamp - start, args[2]);
}

tick-1sec
/++n == 5/
{
	exit(0);
}

Para ver el cambio sufrido por la prioridad a lo largo del tiempo, escriba el siguiente comando en una ventana:


$ echo $$
139208
$ while true ; do let i=0 ; done

En otra ventana, ejecute la secuencia de comandos y redirija la salida a un archivo:


# dtrace -s ./pritime.d 139208 1 > /tmp/pritime.out
#

Puede utilizar el archivo /tmp/pritime.out que se genera como entrada para un software de trazos para visualizar gráficamente la prioridad a lo largo del tiempo. gnuplot es un paquete de trazos gratuito que se incluye en el CD compañero freeware de Solaris. De forma predeterminada, gnuplot está instalado en /opt/sfw/bin.

tick

Solaris utiliza contabilidad de CPU basado en pulsos de reloj, en el que se activa una interrupción del reloj del sistema en un intervalo fijo, y atribuye la utilización de la CPU a los subprocesos y procesos que se ejecutan al mismo tiempo que el pulso. El ejemplo siguiente muestra cómo utilizar el sondeo tick para observar esta atribución:


# dtrace -n sched:::tick'{@[stringof(args[1]->pr_fname)] = count()}'
^C
  arch                                                              1
  sh                                                                1
  sed                                                               1
  echo                                                              1
  ls                                                                1
  FvwmAuto                                                          1
  pwd                                                               1
  awk                                                               2
  basename                                                          2
  expr                                                              2
  resize                                                            2
  tput                                                              2
  uname                                                             2
  fsflush                                                           2
  dirname                                                           4
  vim                                                               9
  fvwm2                                                            10
  ksh                                                              19
  xterm                                                            21
  Xsun                                                             93
  MozillaFirebird                                                 260

La frecuencia de reloj del sistema varía según el sistema operativo, pero suele estar en el intervalo de los 25 y los 1024 hercios. La frecuencia de reloj del sistema Solaris es ajustable, pero el valor predeterminado es 100 hercios.

El sondeo tick sólo se activa si el reloj del sistema detecta un subproceso que pueda ejecutar. Para utilizar el sondeo tick para observar la frecuencia de reloj del sistema, debe contar con un subproceso que pueda ejecutarse en todo momento. Cree en una ventana una shell en bucle, tal y como se muestra en el ejemplo siguiente:


$ while true ; do let i=0 ; done

Ejecute en otra ventana la siguiente secuencia de comandos:

uint64_t last[int];

sched:::tick
/last[cpu]/
{
	@[cpu] = min(timestamp - last[cpu]);
}

sched:::tick
{
	last[cpu] = timestamp;
}

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

  0          9883789

El intervalo mínimo es 9,8 milisegundos, que indica que la frecuencia de pulso de reloj predeterminada es 10 milisegundos (100 hercios). El mínimo observado suele ser algo inferior a los 10 milisegundos, debido al movimiento.

Uno de los defectos del registro basado en pulsos de reloj es que el reloj del sistema que realiza el registro suele ser también responsable de distribuir las actividades de planificación relacionadas con el tiempo. Como resultado, si un subproceso va a realizar determinada cantidad de trabajo cada pulso de reloj (es decir, cada 10 milisegundos), el sistema realizará un registro superior o inferior al subproceso, en función de si el registro se realiza antes o después de la actividad de planificación de distribución relacionada con el tiempo. En Solaris, el registro se realiza antes de la distribución relacionada con el tiempo. Como resultado, el sistema realizará un registro inferior de los subprocesos que están en ejecución en un intervalo regular. Si dichos subprocesos se encuentran en ejecución durante un tiempo inferior al intervalo de pulso de reloj, pueden "ocultarse" tras el pulso del reloj. El ejemplo siguiente muestra el punto hasta el que el sistema tiene tales subprocesos:

sched:::tick,
sched:::enqueue
{
	@[probename] = lquantize((timestamp / 1000000) % 10, 0, 10);
}

La salida de la secuencia de comandos de ejemplo es dos distribuciones del desplazamiento en milisegundos dentro de un intervalo de diez milisegundos, uno para el sondeo tick y otro para el sondeo enqueue:


# dtrace -s ./tick.d
dtrace: script './tick.d' matched 4 probes
^C
  tick                                              
           value  -------------- Distribution ------------ count    
               6 |                                         0        
               7 |@                                        3        
               8 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   79       
               9 |                                         0        

  enqueue                                           
           value  -------------- Distribution ------------ count    
             < 0 |                                         0        
               0 |@@                                       267      
               1 |@@                                       300      
               2 |@@                                       259      
               3 |@@                                       291      
               4 |@@@                                      360      
               5 |@@                                       305      
               6 |@@                                       295      
               7 |@@@@                                     522      
               8 |@@@@@@@@@@@@                             1315     
               9 |@@@                                      337

El histograma de salida denominado tick muestra que el pulso de reloj se está activando con un desplazamiento de 8 milisegundos. Si la planificación no estuviera relacionada de ningún modo con el pulso de reloj, la salida de enqueue estaría distribuida de forma uniforme a lo largo del intervalo de diez milisegundos. Sin embargo, la salida muestra un pico en el mismo desplazamiento de 8 milisegundos, que indica que al menos algunos subprocesos del sistema están planificándose en base al tiempo.

Estabilidad

El proveedor sched utiliza el mecanismo de estabilidad de DTrace para describir sus estabilidades, tal y como se muestra en la tabla siguiente. Para obtener más información sobre el mecanismo de estabilidad, consulte el Capítulo 39Estabilidad.

Elemento 

Estabilidad del nombre 

Estabilidad de los datos 

Clase de dependencia 

Proveedor 

Evolutivo 

Evolutivo 

ISA

Módulo 

Privado 

Privado 

Desconocido 

Función 

Privado 

Privado 

Desconocido 

Nombre 

Evolutivo 

Evolutivo 

ISA

Argumentos 

Evolutivo 

Evolutivo 

ISA