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.
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.
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.
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.
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.
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 |
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.
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); }
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.
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.
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.