Guía de seguimiento dinámico de Solaris

Capítulo 38 Consideraciones sobre el rendimiento

Dado que DTrace provoca que el sistema realice trabajos adicionales, habilitar DTrace siempre afecta al rendimiento del sistema en alguna forma. A veces este efecto es insignificante, pero podría convertirse en importante si se habilita un gran número de sondeos con activaciones que carguen el sistema. Este capítulo describe técnicas para minimizar el efecto que DTrace tiene en el rendimiento.

Sondeos con límite habilitado

Las técnicas de instrumentación dinámica permiten a DTrace proporcionar una cobertura del seguimiento sin igual tanto del núcleo como de procesos de usuario arbitrarios. Aunque esta cobertura permite una nueva y revolucionaria aproximación a la conducta del sistema, puede también provocar un efecto de sondeo enorme. Si se habilitan decenas o cientos de miles de sondeos, el efecto en el sistema probablemente será importante. Por lo tanto debe habilitar sólo los sondeos que necesite para resolver el problema. Por ejemplo, no debería habilitar todos los sondeos FBT si una habilitación más concisa también respondiera a su pregunta. Por ejemplo, su pregunta podría permitirle concentrarse en un módulo de interés o función específica.

A la hora de utilizar el proveedor pid debe prestar especial atención. Dado que el proveedor pid puede instrumentar todas las instrucciones, podría habilitar millones de sondeos en una aplicación, ralentizando enormemente el proceso objetivo.

DTrace puede utilizarse también en situaciones en las que deba habilitarse un gran número de sondeos para obtener la respuesta a una pregunta. La habilitación de un gran número de sondeos podría ralentizar en cierto modo el sistema, pero nunca provocará un fallo grave en el sistema. Por lo tanto, si es necesario, no dude en habilitar tantos sondeos como sean necesarios.

Utilizar adiciones

Tal como se analizó en el Capítulo 9Adiciones, las adiciones de DTrace permiten agregar los datos de forma escalable. Podría parecer que las matrices asociativas ofrecen una funcionalidad similar a las adiciones. Sin embargo, y dada su naturaleza de variable global y de propósito general, no pueden ofrecer la escalabilidad lineal de las adiciones. Por lo tanto, siempre que sea posible, utilice las adiciones en lugar de las matrices asociativas. No se recomienda el siguiente ejemplo:

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

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

Es preferible el ejemplo siguiente:

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

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

Utilización de predicados incluibles en memoria caché

Los predicados de DTrace se utilizan para filtrar los datos que no desee a partir del experimento al realizar un seguimiento de los datos sólo si se detecta que una condición determinada es verdadera (true). Si habilita muchos sondeos, normalmente utilizará predicados con un formato que identifique un subproceso o subprocesos de interés, como por ejemplo /self->traceme/ o /pid == 12345/. Aunque muchos de estos predicados se evalúan como un valor falso (false) para la mayor parte de los subprocesos de la mayoría de los sondeos, la evaluación en sí misma puede convertirse en costosa si se realiza en miles de sondeos. Para reducir este coste, DTrace almacena en memoria caché la evaluación de un predicado si incluye sólo variables de subprocesos locales (por ejemplo, /self->traceme/) o variables inmutables (por ejemplo, /pid == 12345/). El coste de evaluar un predicado incluido en memoria caché es mucho menor que el de evaluar un predicado no incluido en caché, especialmente si el predicado implica variables de subproceso local u otras operaciones relativamente costosas. Aunque la inclusión de predicados en memoria intermedia es transparente para el usuario, implica determinadas directrices para la construcción de predicados óptimos, tal y como se muestra en la tabla siguiente:

Incluible en caché 

No incluible en caché 

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->cualquier miembro , curlwpsinfo->cualquier miembro, curpsinfo->cualquier miembro

No se recomienda el siguiente ejemplo:

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

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

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

Es preferible el siguiente ejemplo, que utiliza variables de subprocesos locales:

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

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

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

Para poder incluirlo en memoria caché, un predicado debe contener exclusivamente expresiones incluibles en caché. Los siguientes predicados son todos incluibles en caché:

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

Los siguientes ejemplos, que utilizan variables locales, no son incluibles en caché:

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