Guía de seguimiento dinámico de Solaris

Capítulo 18 Proveedor lockstat

El proveedor lockstat pone a su disposición sistemas de sondeo que pueden utilizarse para percibir estadísticas de contención de bloqueo, o para comprender prácticamente cualquier aspecto de las conductas de bloqueo. El comando lockstat(1M) es en realidad un consumidor de DTrace que utiliza el proveedor lockstat para recopilar los datos no procesados.

Visión general

El proveedor lockstat pone a disposición dos tipos de sondeos: sondeos de evento de contenido y sondeos de evento de retención.

Los sondeos de eventos de contención corresponden a la contención en una primitiva de sincronización, y se activan cuando se fuerza a un subproceso a que espere hasta que un recurso esté disponible. Por norma general, Solaris está optimizado para el caso de no contención, por lo que no se espera que se produzca una contención prolongada. Estos sondeos deberían usarse para comprender los casos en los que surge la contención. Ya que la contención es un subproceso relativamente extraño, la habilitación de sondeos de eventos de contención no afecta al rendimiento de forma sustancial.

Los sondeos de eventos de retención corresponden a la adquisición, liberación o a otro tipo de manipulación de una primitiva de sincronización. Estos sondeos pueden utilizarse para dar respuesta a cuestiones arbitrarias relacionadas con el modo en el que se manipulan las primitivas de sincronización. Dado que Solaris adquiere y libera primitivas de sincronización muy a menudo (en el orden de millones de veces por segundo y CPU en un sistema con mucho movimiento), habilitar los sondeos de eventos de retención tiene un efecto de sondeo mucho más alto que habilitar los sondeos de eventos de contención. Mientras que el efecto de sondeo que se induce al habilitarlos puede ser sustancial, no es patológico; podrá habilitarlos sin miedo en sistemas de producción.

El proveedor lockstat pone a su disposición sondeos que se corresponden con los diversas primitivas de sincronización de Solaris. Estas primitivas y sus correspondientes sondeos se tratan en el resto de este capítulo.

Sondeos de bloqueo adaptativo

Los bloqueos adaptativos fuerzan la exclusión mutua a una sección crítica, y pueden obtenerse en la mayoría de los contextos dentro del núcleo. Dado que los bloqueos adaptativos tienen un número reducido de restricciones de contexto, cubren la gran mayoría de primitivas de sincronización del núcleo de Solaris. Estos bloqueos son adaptativos en su comportamiento con respecto a la contención: cuando un subproceso intenta adquirir un bloqueo adaptativo mantenido, determinará si el subproceso propietario se encuentra en ejecución en una CPU. Si el propietario se encuentra en ejecución en otra CPU, el subproceso que adquiere se girará. Si el propietario no se encuentra en ejecución, el subproceso que se adquiere se bloqueará.

Los cuatro sondeos lockstat que forman parte de los bloqueos adaptativos se encuentran en la Tabla 18–1. Para cada sondeo, arg0 contiene un puntero a la estructura kmutex_t que representa el bloqueo adaptativo.

Tabla 18–1 Sondeos de bloqueo adaptativo

adaptive-acquire

Sondeo de evento de retención que se activa inmediatamente después de adquirir un bloqueo adaptativo. 

adaptive-block

Sondeo de evento de contención que se activa después de la reactivación de un subproceso que se ha bloqueado en un mutex adaptativo retenido y tras la adquisición por su parte del mutex. Si se encuentran habilitados ambos sondeos, adaptive-block se activará antes que adaptive-acquire. Una única adquisición de bloqueo puede activar tanto el sondeo adaptive-block como el sondeo adaptive-spin. arg1 para adaptive-block contiene el tiempo de inactividad en nanosegundos.

adaptive-spin

Sondeo de evento de contención que se activa después de que un subproceso que ha girado en un mutex adaptativo retenido haya adquirido correctamente el mutex. Si ambos se encuentran habilitados, adaptive-spin se activa antes de adaptive-acquire . Una única adquisición de bloqueo puede activar tanto el sondeo adaptive-block como el sondeo adaptive-spin. arg1 para adaptive-spin contiene el tiempo de giros: número de nanosegundos que se han dedicado al bucle de giro antes de adquirir el bloqueo.

adaptive-release

Sondeo de evento de retención que se activa inmediatamente después de liberar un bloqueo adaptativo. 

Sondeos de bloqueo de giro

Los subprocesos no pueden bloquearse en determinados contextos en el núcleo, como por ejemplo un contexto de interrupción de alto nivel y cualquier contexto que manipule el estado distribuidor. En estos contextos, esta restricción evita el uso de bloqueos adaptativos. En su lugar se utilizan bloqueos de giro para realizar la exclusión mutua a secciones críticas. Tal y como indica su nombre, la conducta de estos bloqueos en la presencia de contención es girar hasta que el subproceso propietario libera el bloqueo. Los tres sondeos relacionados con los bloqueos de giro se encuentran en la Tabla 18–2.

Tabla 18–2 Sondeos de bloqueo de giro

spin-acquire

Sondeo de evento de retención que se ejecuta inmediatamente después de adquirir un bloqueo de giro. 

spin-spin

Sondeo de evento de contención que se activa después de que un subproceso que ha girado en un bloqueo de giro retenido haya adquirido correctamente el bloqueo de giro. Si se encuentran habilitados ambos sondeos, spin-spin se activará antes que spin-acquire. arg1 para spin-spin contiene el tiempo de giros: número de nanosegundos que se han dedicado al estado de giro antes de adquirir el bloqueo. El significado del número de giros por sí mismo es reducido, pero puede utilizarse para comparar los tiempos de giro.

spin-release

Sondeo de evento de retención que se activa inmediatamente después de liberar un bloqueo de giro. 

Los bloqueos adaptativos son mucho más comunes que los bloqueos de giro. La siguiente secuencia de comandos muestra los totales de ambos tipos de bloqueo, para proporcionar datos que sirvan como soporte a esta observación.

lockstat:::adaptive-acquire
/execname == "date"/
{
	@locks["adaptive"] = count();
}

lockstat:::spin-acquire
/execname == "date"/
{
	@locks["spin"] = count();
}

Ejecute esta secuencia de comandos en una ventana, y el comando date(1) en otra. Cuando finalice la secuencia de comandos DTrace verá un resultado similar al siguiente ejemplo:


# dtrace -s ./whatlock.d
dtrace: script './whatlock.d' matched 5 probes 
^C
spin                                                             26
adaptive                                                       2981

Tal y como indica este resultado, más del 99 por ciento de los bloqueos adquiridos durante la ejecución del comando date son bloqueos adaptativos. Puede resultar sorprendente que se adquieran tantos bloqueos al hacer algo tan simple como un date. El gran número de bloqueos es un artefacto natural del bloqueo de alta granularidad requerido en un sistema extremadamente escalable, como el núcleo de Solaris.

Bloqueos de subprocesos

Los bloqueos de subprocesos son un tipo especial de bloqueo de giro que se utilizan para bloquear un subproceso con la finalidad de cambiar su estado.. Los eventos de retención de bloqueo de subprocesos están disponibles como sondeos de eventos de retención de bloqueo de giro (es decir, spin-acquire y spin-release), pero los eventos de contención cuentan con sus propios sondeos específicos para bloqueos de subprocesos. El sondeo de evento de retención de bloque de subprocesos se encuentra en la Tabla 18–3.

Tabla 18–3 Sondeo de bloqueo de subprocesos

thread-spin

Sondeo de evento de contención que se activa después de que un subproceso gire en un bloqueo de subproceso. Al igual que otros sondeos de eventos de contención, si se encuentran habilitadas tanto el sondeo de evento de contención como el sondeo de evento de retención, thread-spin se activará antes de spin-acquire. Sin embargo, a diferencia de otros sondeos de eventos de contención, el giro de subproceso se activa antes de adquirir realmente el bloqueo. Por lo tanto, la activación de varios sondeos thread-spin podrían corresponder a una única activación de sondeo spin-acquire.

Sondeos de bloqueo lectores/escritor

Los bloqueos de lector/escritor hacen cumplir la política de permitir varios lectores o un único escritor, pero no que ambos se encuentren en una sección crítica. Estos bloqueos suelen utilizarse con estructuras que se buscan con más frecuencia que con la que se modifican, y con estructuras de las que hay tiempo sustancial en la sección crítica. Si los tiempos de la sección crítica son breves, los bloqueos lectores/escritor serializarán de forma implícita sobre la memoria utilizada para implementar el bloqueo, no proporcionándoles ventajas frente a otros bloqueos adaptativos. Consulte rwlock(9F) para obtener más detalles acerca de los bloqueos de lector/escritor.

Los sondeos relacionados con los bloqueos de lector/escritor se encuentran en la Tabla 18–4. Para cada sondeo, arg0 contiene un puntero a la estructura krwlock_t que representa el bloqueo adaptativo.

Tabla 18–4 Sondeos de bloqueo lectores/escritor

rw-acquire

Sondeo de evento de retención que se activa inmediatamente después de adquirir un bloqueo lectores/escritor. arg1 contiene la constante RW_READER si el bloqueo se adquirió como lector, y RW_WRITER si el bloqueo se adquirió como escritor.

rw-block

Sondeo de evento de contención que se activa después de que un subproceso que se ha bloqueado en un bloqueo lectores/escritor se haya reactivado y haya adquirido el bloqueo. arg1 contiene la cantidad de tiempo (en nanosegundos) durante la que el subproceso actual tiene que estar inactivo para adquirir el bloqueo. arg2 contendrá la constante RW_READER si se adquirió el bloqueo como lector, y RW_WRITER si se adquirió como escritor. arg3 y arg4 contienen más información de la razón del bloqueo. arg3 no es cero sólo si el bloqueo se retuvo como escritor al realizar el bloqueo del subproceso actual. arg4 contiene el número de lectores al realizar el bloqueo del subproceso actual. Si están habilitados tanto el sondeo rw-block como el sondeo rw-acquire, rw-block se activa antes que rw-acquire.

rw-upgrade

Sondeo de evento de retención que se activa después de que un subproceso haya actualizado satisfactoriamente un bloqueo lectores/escritor de un lector a un escritor. Las actualizaciones no presentan un evento de contención asociado, dado que sólo son posibles a través de una interfaz de no bloqueo, rw_tryupgrade(9F).

rw-downgrade

Sondeo de evento de retención que se activa después de que un subproceso haya degradado su nivel de propiedad de un bloqueo lectores/escritor de escritor a lector. La degradación no tiene evento de contención asociado, ya que siempre se realizan correctamente sin contención. 

rw-release

Sondeo de evento de retención que se activa inmediatamente después de liberar un bloqueo lectores/escritor. arg1 contendrá la constante RW_READER si el bloqueo que se ha liberado se retenía como lector, y RW_WRITER si el bloqueo liberado se retenía como escritor. Debido a las actualizaciones y las degradaciones, puede que el bloqueo no se haya liberado del mismo modo en el que se adquirió.

Estabilidad

El proveedor lockstat utiliza el mecanismo de estabilidad de DTrace para describir las estabilidades, tal 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 

Común

Módulo 

Privado 

Privado 

Desconocido 

Función 

Privado 

Privado 

Desconocido 

Nombre 

Evolutivo 

Evolutivo 

Común

Argumentos 

Evolutivo 

Evolutivo 

Común