Manuel de suivi dynamique Solaris

Chapitre 38 Considérations sur les performances

DTrace entraînant une charge supplémentaire sur le système, son activation affecte toujours la performance du système. Cet effet est souvent minime, mais il peut devenir important si plusieurs sondes utilisant beaucoup de ressources sont activées. Ce chapitre décrit des techniques de réduction de l'effet de DTrace sur la performance.

Limitation des sondes activées

Des techniques d'instrumentation dynamiques permettent à DTrace de proposer une couverture de suivi inégalée du noyau et des processus utilisateur arbitraires. Cette couverture offre non seulement une nouvelle approche révolutionnaire du comportement du système, mais peut également entraîner un effet de sonde considérable. Si des centaines ou des milliers de sondes sont activées, l'effet sur le système peut devenir facilement substantiel. Vous ne devez donc activer que les sondes nécessaires à la résolution d'un problème. Vous ne devez pas, par exemple, activer toutes les sondes FBT si une activation plus précise peut répondre à votre question. Par exemple, votre question peut vous permettre de vous concentrer sur un module ou une fonction spécifique.

Soyez tout particulièrement vigilant en cas d'utilisation du fournisseur pid. Le fournisseur pid pouvant instrumentaliser chaque instruction, vous pourriez activer des millions de sondes dans une application, et ralentir ainsi le processus cible.

DTrace peut également être utilisé dans des situations où un grand nombre de sondes doit être activé pour répondre à une question. L'activation d'un grand nombre de sondes peut ralentir légèrement le système, mais n'entraînera jamais d'erreur fatale sur la machine. N'hésitez donc pas à activer de nombreuses sondes si nécessaire.

Utilisation de groupements

Tel que décrit dans le Chapitre9Groupements, les groupements DTrace offrent une méthode évolutive de regroupement de données. Des ensembles associatifs peuvent sembler offrir des fonctions similaires aux groupements. Cependant, en raison de leur nature globale propre aux variables universelles, ils n'offrent pas l'évolutivité linéaire des groupements. Dans la mesure du possible, privilégiez donc l'utilisation de groupements sur les ensembles associatifs. L'exemple suivant n'est pas recommandé :

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

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

L'exemple suivant est préférable :

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

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

Utilisation de prédicats pouvant être mis en cache

Les prédicats DTrace permettent de filtrer des données inutiles de l'expérimentation en suivant des données suivies uniquement si une condition spécifiée s'avère ne pas être vraie. Lors de l'activation de nombreuses sondes, vous utilisez généralement des prédicats sous une forme identifiant un ou plusieurs threads spécifiques, comme /self->traceme/ ou /pid == 12345/. Bien qu'un grand nombre de ces prédicats évaluent une valeur fausse pour la plupart des threads d'une majorité de sondes, l'évaluation elle-même peut consommer beaucoup de ressources si elle est effectuée par plusieurs centaines de sondes. Pour réduire cette consommation, DTrace met en cache l'évaluation d'un prédicat s'il ne contient que des variables locales de thread (par exemple, /self->traceme/) ou des variables non mutables (par exemple, /pid == 12345/). La consommation de l'évaluation d'un prédicat mis en cache est bien inférieure à celle de l'évaluation d'un prédicat non mis en cache, tout particulièrement si le prédicat implique des variables locales de thread, des comparaisons de chaîne ou d'autres opérations qui consomment relativement beaucoup de ressources. Alors que la mise en cache d'un prédicat est transparente pour l'utilisateur, elle implique certaines autres directives de construction de prédicats optimum, tel qu'illustré dans le tableau suivant :

Peut être mis en cache 

Ne peut pas être mis en 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->tout membre, curlwpsinfo->tout membre, curpsinfo->tout membre

L'exemple suivant n'est pas recommandé :

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

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

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

L'exemple suivant utilisant des variables locales de thread est préférable :

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

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

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

Pour pouvoir être mis en cache, un prédicat doit être constitué exclusivement d'expressions pouvant être mises en cache. Les prédicats suivants peuvent tous être mis en cache :

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

Les exemples suivants, qui utilisent des variables globales, ne peuvent pas être mis en cache :

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