Guia de rastreamento dinâmico Solaris

Capítulo 18 Provedor lockstat

O provedor lockstat disponibiliza os testes que podem ser usados para discernir estatísticas de contenção de bloqueio ou para entender praticamente qualquer aspecto do comportamento de bloqueio. O comando lockstat(1M) é realmente um consumidor do DTrace que usa o provedor lockstat para recolher seus dados básicos.

Visão geral

O provedor lockstat disponibiliza dois tipos de testes: testes de evento de conteúdo e testes de evento de manutenção.

Evento de contenção os testes correspondem à contenção em uma sincronização primitiva, e são acionados quando um segmento é forçado a aguardar que um recurso se torne disponível. O Solaris é geralmente otimizado para o caso de não-contenção, sendo assim, a contenção prolongada não é esperada. Estes testes devem ser usados para compreender esses casos onde a contenção acontece. Como a contenção é relativamente rara, ativar os testes de evento de contenção geralmente não afeta substancialmente o desempenho.

Testes de evento de manutenção que correspondem a adquirir, liberar ou manipular uma sincronização primitiva. Estes testes podem ser usados para responder a questões arbitrárias sobre a forma em que as sincronizações primitivas são manipuladas. Como o Solaris adquire e libera as sincronizações primitivas muito freqüentemente (na ordem de milhões de vezes por segundo por CPU em um sistema ocupado), ativar testes de evento de manutenção tem um efeito de teste muito mais alto que ativar os testes de evento de contenção. Enquanto o efeito de teste induzido pela ativação deles pode ser substancial, ele não é patológico; eles ainda podem ser ativados com confiança em sistemas de produção.

O provedor lockstat disponibiliza os testes que correspondem às sincronizações primitivas diferentes no Solaris; estas primitivas e os testes que correspondem a elas são discutidas no restante deste capítulo.

Testes de bloqueio adaptativo

Os bloqueios adaptativos reforçam a exclusão mútua de uma seção crítica, e podem ser adquiridos na maioria dos contextos do kernel. Como os bloqueios adaptativos possuem algumas restrições de contexto, eles possuem a vasta maioria de sincronizações primitivas no kernel do Solaris. Estes bloqueios são adaptativos em seu comportamento com relação à contenção: quando um segmento tenta adquirir um bloqueio adaptativo mantido, ele determinará se o segmento proprietário está sendo executado atualmente em uma CPU. Se o proprietário estiver sendo executado em outra CPU, o segmento de aquisição irá girar. Se o proprietário não estiver sendo executado, o segmento de aquisição será bloqueado.

Os quatro testes lockstat que pertencem aos bloqueios adaptativos estão na Tabela 18–1. Para cada teste, arg0 contém um ponteiro para a estrutura kmutex_t que representa o bloqueio adaptativo.

Tabela 18–1 Testes de bloqueio adaptativo

adaptive-acquire

Teste de evento de manutenção que é acionado imediatamente depois que um bloqueio adaptativo é adquirido. 

adaptive-block

Teste de evento de contenção que é acionado depois que um segmento bloqueado em um mutex adaptativo mantido foi acionado novamente e adquiriu o mutex. Se ambos os testes forem ativados, adaptive-block é acionado antes de adaptive-acquire. Uma aquisição de bloqueio simples aciona os testes adaptive-block e adaptive-spin. arg1 de adaptive-block contém o tempo de espera em nanossegundos.

adaptive-spin

Teste de evento de contenção que é acionado depois que um segmento girado em um mutex adaptativo mantido adquiriu o mutex com êxito. Se ambos os testes forem ativados, adaptive-spin é acionado antes de adaptive-acquire. Uma aquisição de bloqueio simples aciona os testes adaptive-block e adaptive-spin. arg1 de adaptive-spin contém o tempo dos giros: a quantidade de nanossegundos que o ciclo de giros gastou antes que o bloqueio fosse adquirido.

adaptive-release

Teste de evento de manutenção que é acionado imediatamente depois que um bloqueio adaptativo é liberado. 

Testes de bloqueio de giro

Os segmentos não podem ser bloqueados em alguns contextos no kernel, tais como contexto de interrupção de alto nível e qualquer estado do distribuidor de manipulação de contexto. Nestes contextos, esta restrição impede o uso de bloqueios adaptativos. Bloqueios de giro são usados para realizar exclusão mútua de seções críticas nestes contextos. Como o nome sugere, o comportamento destes bloqueios na presença de contenção é gerar até que o bloqueio seja liberado por seu segmento proprietário. Os três testes que pertencem aos bloqueios de giro estão na Tabela 18–2.

Tabela 18–2 Testes de bloqueio de giro

spin-acquire

Teste de evento de manutenção que é acionado imediatamente depois que um bloqueio de giro é adquirido. 

spin-spin

Teste de evento de contenção que é acionado depois que um segmento girado em um bloqueio de giro mantido adquiriu o bloqueio de giro com êxito. Se ambos os testes forem ativados, spin-spin é acionado antes de spin-acquire. arg1 de spin-spin contém o tempo dos giros: a quantidade de nanossegundos gasta no estado do giro antes que o bloqueio fosse adquirido. A contagem de giros tem pouca importância, mas pode ser usada para comparar tempos de giro.

spin-release

Teste de evento de manutenção que é acionado imediatamente depois que um bloqueio de giro é liberado. 

Os bloqueios adaptativos são muito mais comuns que os bloqueios de giro. O script seguinte exibe os totais de ambos os tipos de bloqueio para fornecer dados que dêem suporte a esta observação.

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

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

Execute este script em uma janela e o comando date(1) em outra. Quando terminar o script do DTrace, você verá uma saída semelhante ao exemplo seguinte:


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

Como esta saída indica, mais de 99% dos bloqueios adquiridos na execução do comando date são bloqueios adaptativos. Talvez seja surpreendente que tantos bloqueios sejam adquiridos quando se faz algo tão simples como executar o comando date. O grande número de bloqueios é um artefato natural do bloqueio refinado requerido de um sistema extremamente escalável como o kernel do Solaris.

Bloqueios de segmento

Os bloqueios de segmento são um tipo especial de bloqueio de giro usados para bloquear um segmento com a finalidade de alterar o estado do segmento. Os eventos de manutenção de bloqueio de segmento estão disponíveis como testes de evento de manutenção de bloqueio de giro (ou seja, spin-acquire e spin-release), mas os eventos de contenção possuem seu próprio teste específico para bloqueios de segmento. O teste do evento de manutenção de bloqueio de segmento está na Tabela 18–3.

Tabela 18–3 Testes de bloqueio de segmento

thread-spin

Teste de evento de contenção que é acionado depois que um segmento tiver girado em um bloqueio de segmento. Como em outros testes de evento de contenção, se o teste de evento de contenção e o teste de evento de manutenção forem acionados, thread-spin será acionado antes de spin-acquire. Ao contrário dos testes de evento de contenção, entretanto, thread-spin é acionado antes que o bloqueio seja realmente adquirido. Conseqüentemente, vários acionamentos do teste thread-spin podem corresponder a um único acionamento do teste spin-acquire.

Testes de bloqueio de leitores/gravador

Os bloqueios de leitor/gravador forçam uma política de permissão de vários leitores ou um único gravador, mas não ambos, em uma seção crítica. Estes bloqueios são geralmente usados para estruturas que são pesquisadas mais freqüentemente do que modificadas, e para as quais existe tempo substancial na seção crítica. Se os tempos de seção crítica forem curtos, os bloqueios de leitor/gravador serão implicitamente serializados na memória compartilhada usada para implementar o bloqueio, o que não dá a eles nenhuma vantagem sobre os bloqueios adaptativos. Consulte rwlock(9F) para obter mais detalhes sobre bloqueios de leitores/gravador.

Os testes que pertencem aos bloqueios de leitores/gravador estão na Tabela 18–4. Para cada teste, arg0 contém um ponteiro para a estrutura krwlock_t que representa o bloqueio adaptativo.

Tabela 18–4 Testes de bloqueio de leitores/gravador

rw-acquire

Teste de evento de manutenção que é acionado imediatamente depois que um bloqueio de leitores/gravador é adquirido. arg1 conterá a constante RW_READER, se o bloqueio tiver sido adquirido como um leitor, e RW_WRITER se o bloqueio tiver sido adquirido como um escritor.

rw-block

Teste de evento de contenção que é acionado depois que um segmento bloqueado em um bloqueio de leitores/gravador mantido foi acionado novamente e adquiriu o bloqueio. arg1 contém a duração do tempo (em nanossegundos) que o segmento atual teve que ficar inativo para adquirir o bloqueio. arg2 conterá a constante RW_READER, se o bloqueio tiver sido adquirido como um leitor, e RW_WRITER se o bloqueio tiver sido adquirido como um escritor. arg3 e arg4 contêm mais informações sobre o motivo do bloqueio. arg3 será diferente de zero, se e somente se o bloqueio foi mantido como um escritor quando o segmento atual foi bloqueado. arg4 contém a contagem de leitores quando o segmento atual foi bloqueado. Se os testes rw-block e rw-acquire estiverem ativados, rw-block é acionado antes de rw-acquire.

rw-upgrade

Teste de evento de manutenção que é acionado depois que um segmento tiver atualizado com êxito um bloqueio de leitores/gravador a partir de um leitor para um gravador. As atualizações não possuem um evento de contenção associado porque elas só são possíveis através de uma interface de não-bloqueio, rw_tryupgrade(9F).

rw-downgrade

Teste de evento de manutenção que é acionado depois que um segmento tiver feito downgrade de sua propriedade de um bloqueio de leitores/gravador de gravador para leitor. Os downgrades não possuem um evento de contenção associados porque eles sempre acontecem sem contenção. 

rw-release

Teste de evento de manutenção que é acionado imediatamente depois que um bloqueio de leitores/gravador é liberado. arg1 conterá a constante RW_READER, se o bloqueio liberado tiver sido mantido como um leitor, e RW_WRITER se o bloqueio liberado tiver sido mantido como um gravador. Devido aos upgrades e downgrades, o bloqueio pode não ter sido liberado quando foi adquirido.

Estabilidade

O provedor lockstat usa o mecanismo de estabilidade do DTrace para descrever suas estabilidades, conforme mostrado na tabela seguinte. Para obter mais informações sobre o mecanismo de estabilidade, consulte o Capítulo 39Estabilidade.

Elemento 

Estabilidade de nome 

Estabilidade de dados 

Classe de dependência 

Provedor 

Desenvolvendo 

Desenvolvendo 

Comum

Módulo 

Privada 

Privada 

Desconhecida 

Função 

Privada 

Privada 

Desconhecida 

Nome 

Desenvolvendo 

Desenvolvendo 

Comum

Argumentos 

Desenvolvendo 

Desenvolvendo 

Comum