Guia de rastreamento dinâmico Solaris

Capítulo 11 Buffers e armazenamento em buffer

O armazenamento de dados em buffer e o seu gerenciamento são serviços essenciais fornecidos pela estrutura do DTrace a seus clientes, como o dtrace(1M). Este capítulo explora o armazenamento de dados em buffer detalhadamente e descreve opções que podem ser usadas para alterar as políticas de gerenciamento do buffer do DTrace.

Buffers principais

O buffer principal está presente em cada chamada do DTrace e é o buffer no qual as ações de rastreio registram seus dados por padrão. Estas ações incluem:

exit()

printf()

trace()

ustack()

printa()

stack()

tracemem()

 

Os buffers principais sempre são alocados em uma base por CPU. Essa política não é ajustável, mas o rastreio e a alocação do buffer podem ser restritos a uma única CPU usando-se a opção cpu.

Políticas do buffer principal

O DTrace permite o rastreio em contextos altamente restritos no kernel. Em particular, o DTrace permite o rastreio em contextos nos quais a alocação de memória pelo software do kernel possa não ser confiável. A conseqüência dessa flexibilidade de contexto é que sempre existe a possibilidade de que o DTrace irá tentar rastrear os dados quando não houver espaço disponível. O DTrace deve ter uma política para lidar com tais situações quando elas ocorrerem, mas você pode querer ajustar a política com base nas necessidades de um determinado experimento. Algumas vezes a política apropriada pode ser de descartar os novos dados. Outras vezes, talvez seja desejável reutilizar o espaço que contém os dados registrados mais antigos para rastrear novos dados. Mais freqüentemente, a política desejada é de minimizar a probabilidade de ficar sem espaço disponível em primeiro lugar. Para acomodar todas essas demandas, o DTrace oferece suporte a várias políticas de buffer diferentes. Esse suporte é implementado com a opção bufpolicy, e pode ser definido em uma base por consumidor. Consulte o Capítulo 16Opções e ajustáveis para obter detalhes sobre as opções de configuração.

Política switch

Por padrão, o buffer principal possui uma política switch. Nessa política, os buffers por CPU são alocados em pares: um buffer é ativo e ou outro, inativo. Quando um consumidor do DTrace tenta ler um buffer, o kernel primeiro alterna os buffers inativos e ativos. A alternância de buffer é feita de tal maneira que não haja uma janela na qual os dados do rastreio possam se perder. Depois que os buffers forem alternados, o buffer recém-inativo é copiado para o consumidor do DTrace. Essa política garante que o consumidor sempre veja um buffer auto-consistente: um buffer nunca é simultaneamente rastreado e copiado. Essa técnica também impede que seja introduzida uma janela na qual o rastreio seja pausado ou, de alguma forma, impedido. A taxa na qual o buffer é alternado e lido é controlada pelo consumidor com a opção switchrate. Assim como com qualquer opção de taxa, switchrate pode ser especificada com qualquer sufixo de tempo, mas o padrão é taxa por segundo. Para obter mais detalhes sobre switchrate e outras opções, consulte o Capítulo 16Opções e ajustáveis.


Observação –

Para processar o buffer principal no nível do usuário mais rápido que o padrão que é de uma vez por segundo, ajuste o valor de switchrate. O sistema processa as ações que produzem atividade no nível do usuário (como printa () e system()) quando o registro correspondente no buffer principal é processado. O valor de switchrate determina a velocidade na qual o sistema processa tais ações.


Na política switch, se um determinado teste ativado rastrear mais dados do que o espaço disponível no buffer principal ativo, os dados serão cancelados e uma contagem de cancelamento por CPU é incrementada. No caso de um ou mais cancelamentos, o dtrace(1M) exibe uma mensagem similar ao seguinte exemplo:


dtrace: 11 drops on CPU 0

Se um determinado registro for maior que o tamanho total do buffer, o registro será cancelado independentemente da política do buffer. Você pode reduzir ou eliminar cancelamentos, seja aumentando o tamanho do buffer principal com a opção bufsize ou aumentando a taxa de alternância com a opção switchrate .

Na política switch, o espaço temporário para copyin(), copyinstr() e alloca() é alocado fora do buffer ativo.

Política fill

Para alguns problemas, você pode querer usar um único buffer em kernel. Embora essa abordagem possa ser implementada com a política switch e construções apropriadas de D incrementando-se uma variável em D e criando-se um predicado para uma ação exit() apropriadamente, tal implementação não elimina a possibilidade de cancelamentos. Para solicitar um único buffer grande em kernel e prosseguir com o rastreio até que um ou mais dos buffers por CPU tenha sido preenchido, use a política de buffer fill. Nessa política, o rastreio continua até que um teste ativado tente rastrear mais dados que possam caber no espaço restante do buffer principal. Quando não houver espaço suficiente restante, o buffer é marcado como preenchido e o consumidor é notificado que pelo menos um dos buffers por CPU foi preenchido. Quando o dtrace(1M) detecta um único buffer preenchido, o rastreio é interrompido, todos os buffers são processados e dtrace é encerrado. Dados adicionais não serão rastreados para um buffer preenchido mesmo que esses dados caibam nele.

Para usar a política fill, defina a opção bufpolicy como fill. Por exemplo, o seguinte comando rastreia cada entrada de chamada do sistema em um buffer por CPU de 2K com a política de buffer definida como fill:


# dtrace -n syscall:::entry -b 2k -x bufpolicy=fill

Política fill e testes END

Os testes END normalmente não são acionados até que o rastreio tenha sido explicitamente interrompido pelo consumidor do DTrace. É garantido que os testes END sejam acionados apenas em uma CPU, mas a CPU na qual o teste é acionado não é definida. Com buffers fill, o rastreio é explicitamente interrompido quando pelo menos um dos buffers principais por CPU tiver sido marcado como preenchido. Se a política fill estiver selecionada, o teste END pode ser acionado em uma CPU que possua um buffer preenchido. Para acomodar o rastreio END em buffers fill, o DTrace calcula a quantidade de espaço potencialmente consumido pelos testes END e subtrai esse espaço do tamanho do buffer principal. Se o tamanho líquido for negativo, o DTrace se recusará a iniciar e o dtrace(1M) retornará uma mensagem de erro correspondente:


dtrace: END enablings exceed size of principal buffer

O mecanismo de reserva garante que um buffer completo sempre possui espaço suficiente para quaisquer testes END.

Política ring

A política de buffer ring do DTrace auxilia no rastreio de eventos que levam a falha. Se a reprodução da falha demorar horas ou dias, talvez você queira manter somente os dados mais recentes. Depois que um buffer principal for preenchido, o rastreio retorna para a primeira entrada, sobrescrevendo dados de rastreio antigos. Estabeleça o buffer de anel, configurando a opção bufpolicy para a seqüência ring:


# dtrace -s foo.d -x bufpolicy=ring

Quando usado para criar um buffer de anel, o dtrace(1M) não exibirá qualquer resultado até que o processo esteja terminado. Nesse momento, o buffer de anel estará consumido e processado. O dtrace processa cada buffer de anel em ordem de CPU. Em um buffer de CPU, os registros do rastreio serão exibidos na ordem do mais antigo para o mais novo. Assim como na política de buffer switch, não existe ordem entre os registros de CPUs diferentes. Se for necessária uma ordem, você deve rastrear a variável timestamp como parte da solicitação de rastreio.

O exemplo a seguir demonstra o uso de uma diretiva #pragma option para ativar o buffer em anel:

#pragma D option bufpolicy=ring
#pragma D option bufsize=16k

syscall:::entry
/execname == $1/
{
	trace(timestamp);
}

syscall::rexit:entry
{
	exit(0);
}

Outros buffers

Os buffers principais existem em todas as ativações do DTrace. Além dos buffers principais, alguns consumidores do DTrace podem ter buffers de dados adicionais em kernel: um buffer de agregação, discutido no Capítulo 9Agregações e um ou mais buffers especulativos, discutidos no Capítulo 13Rastreio especulativo.

Tamanhos de buffer

O tamanho de cada buffer pode ser ajustado em uma base por consumidor. Opções separadas são fornecidas para ajustar o tamanho de cada buffer, conforme mostrado na tabela a seguir:

Buffer 

Opção de tamanho 

Principal 

bufsize

Especulativo 

specsize

Agregação 

aggsize

Cada uma destas opções é definida com um valor que denota o tamanho. Assim como com qualquer opção de tamanho, o valor pode ter um sufixo de tamanho opcional. Consulte o Capítulo 16Opções e ajustáveis para obter mais detalhes. Por exemplo, para definir o tamanho do buffer como um megabyte na linha de comando de dtrace, você pode usar -x para definir a opção:


# dtrace -P syscall -x bufsize=1m

Como alternativa, você pode usar a opção -b para dtrace :


# dtrace -P syscall -b 1m

Finalmente, você pode definir bufsize usando #pragma D option:

#pragma D option bufsize=1m

O tamanho de buffer selecionado denota o tamanho do buffer em cada CPU. Além disso, para a política de buffer switch, bufsize denota o tamanho de cada buffer em cada CPU. O padrão do tamanho de buffer é quatro megabytes.

Política de redimensionamento de buffer

Ocasionalmente, o sistema pode não ter memória de kernel livre adequada para alocar um buffer de tamanho desejado seja porque não há memória suficiente disponível ou porque o consumidor do DTrace excedeu um dos limites ajustáveis descritos no Capítulo 16Opções e ajustáveis. Você pode configurar a política para falha de alocação de buffer usando a opção bufresize , que tem como padrão auto. Na política de redimensionamento de buffer auto, o tamanho de um buffer é dividido até que uma alocação bem-sucedida ocorra. dtrace(1M) gera uma mensagem se um buffer alocado for menor que o tamanho solicitado:


# dtrace -P syscall -b 4g
dtrace: description 'syscall' matched 430 probes
dtrace: buffer size lowered to 128m
...

ou:


# dtrace -P syscall'{@a[probefunc] = count()}' -x aggsize=1g
dtrace: description 'syscall' matched 430 probes
dtrace: aggregation size lowered to 128m
...

Como alternativa, você pode requerer intervenção manual após falha na alocação do buffer definindo bufresize como manual. Nessa política, uma falha de alocação fará com que o DTrace deixe de ser iniciado:


# dtrace -P syscall -x bufsize=1g -x bufresize=manual
dtrace: description 'syscall' matched 430 probes
dtrace: could not enable tracing: Not enough space
#

A política de redimensionamento de buffer de todos os buffers, principal, especulativo e agregação, é ditada pela opção bufresize.