Guia de rastreamento dinâmico Solaris

Capítulo 38 Considerações sobre o desempenho

Como o DTrace causa trabalho adicional no sistema, sua ativação sempre afeta o desempenho do sistema de alguma maneira. Geralmente, esse efeito não é significativo, mas pode se tornar substancial se houver muitas ativações de testes de custo elevado. Este capítulo descreve técnicas para minimizar o efeito no desempenho do DTrace.

Limitar testes ativados

Técnicas de instrumentação dinâmicas permitem que o DTrace forneça uma cobertura de rastreio sem igual do kernel e dos processos arbitrários do usuário. Embora essa cobertura permita uma nova e revolucionária abordagem do comportamento do sistema, ela também pode causar um efeito enorme nos testes. Se milhares de testes forem ativados, o efeito no sistema pode, facilmente, ser substancial. Portanto, você deve ativar somente o número de testes necessários para solucionar um problema. Você não deve, por exemplo, ativar todos os testes FBT se uma ativação mais concisa for capaz de responder à sua pergunta. Por exemplo, sua pergunta pode permitir que você se concentre em um módulo específico de interesse ou uma função específica.

Ao usar o provedor pid, você deve ter um cuidado especial. Como o provedor pid pode instrumentar todas as instruções, você pode ativar milhões de testes em um aplicativo, tornando o processo de destino extremamente lento.

O DTrace também pode ser usado em situações nas quais grandes quantidades de testes precisem ser ativadas para que uma pergunta seja respondida. A ativação de muitos testes pode tornar um sistema um pouco lento, mas nunca induzirá a uma falha grave no computador. Assim, você não deve hesitar se for necessário ativar muitos testes.

Usar agregações

Conforme discutido no Capítulo 9Agregações, as agregações do DTrace permitem uma maneira escalável de agregar dados. As matrizes de associação podem parecer possuir uma funcionalidade similar às agregações. Entretanto, por serem variáveis de natureza global, com várias finalidades, elas não podem oferecer a escalabilidade linear das agregações. Você deve, portanto, preferir usar agregações em matrizes de associação quando possível. O exemplo a seguir não é recomendável:

syscall:::entry
{
	totals[execname]++;
}

syscall::rexit:entry
{
	printf("%40s %d\n", execname, totals[execname]);
	totals[execname] = 0;
}

O exemplo a seguir é preferível:

syscall:::entry
{
	@totals[execname] = count();
}

END
{
	printa("%40s %@d\n", @totals);
}

Usar predicados em cache

Os predicados do DTrace são usados para filtrar dados indesejados do experimento, rastreando dados que só são rastreados se uma condição especificada for verdadeira. Ao ativar muitos testes, você geralmente usa predicados de uma forma que identifique um segmento específico ou segmentos do seu interesse, como o /self->traceme/ ou o /pid == 12345/. Embora muitos desses predicados tenham o valor falso na maioria dos segmentos de grande parte dos testes, a própria avaliação pode ter um alto custo quando feita para milhares de testes. Para reduzir esse custo, o DTrace armazena em cache o valor do predicado se ele incluir somente variáveis de segmentos locais (por exemplo, /self->traceme/) ou variáveis imutáveis (por exemplo, /pid == 12345/). O custo da avaliação de um predicado em cache é muito menor que o custo da avaliação de um predicado que não esteja em cache, especialmente se o predicado envolver variáveis de segmentos locais, comparações de seqüências, ou outras operações de custo relativamente elevado. Embora o cache de predicados seja transparente para o usuário, é necessário que sejam seguidas algumas instruções para a construção de predicados perfeitos, conforme mostrado na tabela a seguir:

Pode ser armazenado em cache 

Não pode ser armazenado em cache 

self->mumble

mumble[curthread], mumble[pid, tid]

execname

curpsinfo->pr_fname, curthread->t_procp->p_user.u_comm

pid

curpsinfo->pr_pid, curthread->t_procp->p_pipd->pid_id

tid

curlwpsinfo->pr_lwpid, curthread->t_tid

curthread

curthread->qualquer membro , curlwpsinfo->qualquer membro, curpsinfo->qualquer membro

O exemplo a seguir não é recomendável:

syscall::read:entry
{
	follow[pid, tid] = 1;
}

fbt:::
/follow[pid, tid]/
{}

syscall::read:return
/follow[pid, tid]/
{
	follow[pid, tid] = 0;
}

O exemplo a seguir usando variáveis de segmentos locais é preferível:

syscall::read:entry
{
	self->follow = 1;
}

fbt:::
/self->follow/
{}

syscall::read:return
/self->follow/
{
	self->follow = 0;
}

Um predicado deve consistir exclusivamente em expressões armazenáveis em cache para poder ser armazenado em cache. Todos os predicados a seguir podem ser armazenados em cache:

/execname == "myprogram"/
/execname == $$1/
/pid == 12345/
/pid == $1/
/self->traceme == 1/

Os exemplos a seguir, que usam variáveis globais, não podem ser armazenados em cache:

/execname == one_to_watch/
/traceme[execname]/
/pid == pid_i_care_about/
/self->traceme == my_global/