mageekblog - Mot-clé - DLe blog personnel de Frédéric Hardy. Au menu, PHP, agilité, FreeBSD, cuisine et photographies.2021-12-02T08:20:54+01:00Frédéric Hardyurn:md5:26874ca5b8cd4cac8d08b0e68e64f63aDotclearDTrace un peu plus dans le détailurn:md5:d07aeed48a514d1c0962a5c4c16e62422010-06-16T22:00:00+02:002010-06-16T22:13:14+02:00mageekguyPHP XDDTracefirefoxgdbhttpdmysqlPHPPHP X<p>Durant la séance de questions qui a suivi ma conférence <q><a href="http://www.slideshare.net/impossiblium/php-retour-vers-le-futur">PHP : retour vers le futur !</a></q> que j'ai donné au cours de <a href="http://blog.mageekbox.net/?post/2010/06/12/%24aperoPhp">l'apéro PHP lillois du 11 juin 2010</a>, <code>DTrace</code> a été le sujet qui est très nettement ressorti.</p>
<p>Il m'a été demandé entre autre l'intérêt que cet outil avait par rapport à <a href="http://en.wikipedia.org/wiki/GNU_Debugger"><code>gdb</code></a> et la façon de le mettre en œuvre.</p>
<p>Ma conférence n'étant clairement pas prévue pour rentrer à ce point dans les détails, j'ai répondu aux questions dans les grandes lignes, mais je vais maintenant essayer d'y répondre plus précisément.</p> <p>Je vais donc commencer par vous présenter l'historique de <code>DTrace</code>, je poursuivrai avec son principe de fonctionnement, et enfin je terminerai par un cas d'utilisation dans le cadre d'un développement en <a href="http://www.php.net">PHP</a>.</p>
<p><code>DTrace</code> est un outil qui a été créé en 2003 par <a href="http://fr.wikipedia.org/wiki/Sun_Microsystems">Sun Microsystems</a>, dans le cadre du développement de son système d'exploitation <a href="http://fr.wikipedia.org/wiki/Solaris_%28syst%C3%A8me_d%27exploitation%29">Solaris</a>, dans lequel il a été intégré en 2005.</p>
<p>Suite à l'ouverture du code source de ce dernier via le projet <a href="http://fr.wikipedia.org/wiki/OpenSolaris">OpenSolaris</a>, il est devenu un outil libre, régit par la licence <a href="http://fr.wikipedia.org/wiki/Common_Development_and_Distribution_License"><abbr title="Common Development and Distribution Licence">CDDL</abbr></a>.</p>
<p>Son objectif est de permettre de tracer l’exécution d'un programme, de manière transparente et sans aucune perte de performance, afin qu'il puisse être mis en œuvre dans des environnements de production.</p>
<p>Le principe de <code>DTrace</code> est basé sur celui du patron de conception <a href="http://fr.wikipedia.org/wiki/Observateur_%28patron_de_conception%29">observateur/observable</a>.</p>
<p>L'observable déclenche lors de son exécution des <q>sondes</q>, ce qui propage un évènement vers les observateurs.</p>
<p>Ces évènements sont interceptés, ou non, par les observateurs, qui sont des scripts en langage <code>D</code>, capables d'effectuer différentes actions en fonction des besoins.</p>
<p>Cette architecture a plusieurs avantages majeurs :</p>
<ul>
<li>Elle est pratique, car il est possible de l'activer à la demande sur un programme en cours d’exécution.</li>
<li>Elle est efficace, car elle permet de ne tracer que ce qui est nécessaire.</li>
<li>Elle est souple, car elle permet de tracer ce que l'on veut, comme par exemple un temps d’exécution, une pile d'appel ou l'utilisation de la mémoire.</li>
<li>Elle ne dégrade pas les performances du programme observé, car tout se passe au niveau du noyau du système d'exploitation.</li>
<li>Elle est capable de tracer plusieurs processus simultanément, ou encore plusieurs niveaux différents de l'application en parallèle.</li>
<li>Elle permet de tracer simultanément l’exécution au niveau de l'environnement de l'utilisateur et au niveau du noyau du système d'exploitation.</li>
</ul>
<p><code>DTrace</code> est donc particulièrement adapté pour diagnostiquer des problèmes réels en temps réel sur des systèmes en production pris dans leur ensemble.</p>
<p>Le principe de <code>DTrace</code> est donc très différent de celui de <a href="http://en.wikipedia.org/wiki/GNU_Debugger"><code>gdb</code></a>.</p>
<p>En effet, de part son principe de fonctionnement, ce dernier ne peut pas faire la même chose que <code>DTrace</code>.</p>
<p>Il est en effet adapté pour résoudre un problème sur un exécutable spécifique, alors que <code>DTrace</code> peut surveiller plusieurs exécutable simultanément, voir même le système d'exploitation, puisque c'est sa vocation première dans le cadre de <a href="http://fr.wikipedia.org/wiki/Solaris_%28syst%C3%A8me_d%27exploitation%29">Solaris</a>.</p>
<p>De plus, <a href="http://en.wikipedia.org/wiki/GNU_Debugger"><code>gdb</code></a> doit être activé au démarrage du programme à observer, alors que <code>DTrace</code> peut être déclenché à tout moment.</p>
<p>Il n'est donc pas du tout conçu pour travailler sur du code en production.</p>
<p>En contrepartie, <a href="http://en.wikipedia.org/wiki/GNU_Debugger"><code>gdb</code></a> peut influencer sur le déroulement du programme, au contraire de <code>DTrace</code> qui ne permet que la collecte d'informations.</p>
<p>Au final, ce ne sont donc pas des outils concurrents, mais bien complémentaires, car ils permettent respectivement de répondre à une problématique différente :</p>
<ul>
<li><code>DTrace</code> permet d'identifier les problèmes sur une application de manière globale.
</li>
<li>Une fois ces problèmes identifiés, <a href="http://en.wikipedia.org/wiki/GNU_Debugger"><code>gdb</code></a> permet de les résoudre de manière locale.
</li>
</ul>
<p>La version du <a href="http://svn.php.net/viewvc/php/php-src/trunk/">trunk</a> de <a href="http://www.php.net">PHP</a> dispose depuis quelques temps maintenant des <q>sondes</q> suivantes :</p>
<ul>
<li><code>request-startup</code>, déclenchée lorsqu'un script <a href="http://www.php.net">PHP</a> est exécuté,</li>
<li><code>request-shutdown</code>, déclenchée lorsque l’exécution d'un script <a href="http://www.php.net">PHP</a> est terminée,</li>
<li><code>compile-file-entry</code>, déclenchée lorsque la compilation d'un script <a href="http://www.php.net">PHP</a> commence,</li>
<li><code>compile-file-return</code>, déclenchée lorsque la compilation d'un script <a href="http://www.php.net">PHP</a> est terminée,</li>
<li><code>execute-entry</code>, déclenchée lors de l’exécution d'un <a href="http://fr.wikipedia.org/wiki/Langage_machine">opcode</a> <a href="http://www.php.net">PHP</a>,</li>
<li><code>execute-return</code>, déclenchée lorsque l’exécution d'un <a href="http://fr.wikipedia.org/wiki/Langage_machine">opcode</a> <a href="http://www.php.net">PHP</a> est terminée,</li>
<li><code>function-entry</code>, déclenchée lors de l’exécution d'une fonction ou d'une méthode <a href="http://www.php.net">PHP</a> commence,</li>
<li><code>function-return</code>, déclenchée lorsque l’exécution d'une fonction ou d'une méthode <a href="http://www.php.net">PHP</a> est terminée,</li>
<li><code>exception-thrown</code>, déclenchée lorsqu'une exception est lancée,</li>
<li><code>exception-caught</code>, déclenchée lorsqu'une exception est attrapée,</li>
<li><code>error</code>, déclenchée lorsqu'une erreur survient au cours de l’exécution.</li>
</ul>
<p>Comme nous l'avons vu, pour les utiliser, il faut passer par un script écrit en langage <code>D</code>.</p>
<p>Attention, contrairement à ce que j'ai affirmé lors de ma conférence, il ne s'agit aucunement du <a href="http://fr.wikipedia.org/wiki/D_%28langage%29">langage D</a> de Walter Bright, mais bien d'un langage spécifique à <code>DTrace</code> dérivé du langage <a href="http://fr.wikipedia.org/wiki/C_%28langage%29%3E%3Ccode%3EC%3C/code%3E%3C/a%3E%20avec%20des%20fonctions%20et%20des%20variables%20sp%C3%A9cifiques,%20et%20qui%20pr%C3%A9sente%20une%20structure%20similaire%20%C3%A0%20un%20script%20%C3%A9crit%20en%20%3Ca%20href=" http:="" fr.wikipedia.org="" wiki="" awk=""><code>awk</code></a>.</p>
<p>Un script en <code>D</code> minimal dispose de la structure suivante :</p>
<blockquote><pre><code>sonde<br />/expression/<br />{<br /> actions<br />}<br /></code></pre></blockquote>
<p>Évidement, il peut y avoir plusieurs bloc de ce type dans un script, afin d'interroger autant de <q>sondes</q> différentes.</p>
<p><code>sonde</code>permet de décrire la sonde qui doit déclencher l'action qui suit, à l'aide de la convention<code>fournisseur:module:fonction:emplacement</code>, ou :</p>
<ul>
<li><code>fournisseur</code> correspond à l'émetteur de la <q>sonde</q>, dans le cas de <a href="http://www.php.net">PHP</a>, il s'agit de <code>php</code>, mais de base, <code>DTrace</code> fourni un grand nombre de fournisseurs, comme profile qui permet de déclencher une <q>sonde</q> à intervalle fixe.</li>
<li><code>module</code> indique le sous-ensemble auquel est rattaché la <q>sonde</q>, par exemple <code>libc</code>.</li>
<li><code>fonction</code> défini le nom de la fonction qui doit déclencher la <q>sonde</q>, par exemple <code>fstat</code>.</li>
<li><code>emplacement</code> permet de dire si la <q>sonde</q> doit se déclencher à la fin ou bien au début de la fonction, à l'aide par exemple des mots-clefs <code>entry</code> ou <code>return</code>.</li>
</ul>
<p>L'attribut <code>expression</code> permet de spécifier une condition qui autorisera l’exécution de l'action, uniquement si elle est vérifiée.</p>
<p>Il est ainsi par exemple possible de cibler un processus spécifique, soit par son nom, soit par son numéro.</p>
<p>Le bloc entre accolade défini quant à lui les actions qui doivent être effectuées lorsque la <q>sonde</q> est déclenchée.</p>
<p><code>DTrace</code> propose de base un grand nombre d'action, comme par exemple :</p>
<ul>
<li><code>printf</code> qui permet d'écrire sur la sortie standard.</li>
<li><code>trace</code> qui permet d'obtenir la valeur d'une variable.</li>
<li><code>ustack</code> qui permet d'obtenir la pile d’exécution.</li>
</ul>
<p>En combinant tout cela, il est possible, par exemple, de surveiller les temps d’exécution respectifs de <a href="http://www.php.net">PHP</a>, de <a href="http://httpd.apache.org">httpd</a>, <a href="http://www.mysql.com">mysql</a> et <a href="http://www.mozilla-europe.org/fr/firefox">firefox</a> :</p>
<blockquote><pre><code>#!/usr/sbin/dtrace -qs<br />BEGIN<br />{<br /> total=mysqlcnt=httpcnt=phpcnt=ffxcnt=0;<br /> printf("%10s %10s %10s %10s\n","% MYSQL","% APACHE","% FIREFOX","% PHP");<br />}<br /><br />php*:::request-startup<br />{<br /> inphp[pid,tid]=1;<br />}<br /><br />php*:::request-shutdown<br />{<br /> inphp[pid,tid]=0;<br />}<br /><br />profile-1001<br />{<br /> total++;<br /> (execname=="mysqld")?mysqlcnt++:\<br /> (execname=="httpd")?(inphp[pid,tid]==1?phpcnt++:httpcnt++):\<br /> (execname=="firefox-bin")?ffxcnt++;<br />}<br /><br />tick-30s<br />{<br /> printf("%10s %10s %10s %10s %10s %10s\n","% MYSQL","% APACHE","% FIREFOX","% PHP");<br />}<br /><br />tick-2s<br />{<br /> printf("%10d %10d %10d %10d %10d %10d\n",mysqlcnt*100/total,httpcnt*100/total,ffxcnt*100/total,phpcnt*100/total);<br /> total=mysqlcnt=httpcnt=phpcnt=ffxcnt=javacnt=othercnt=0;<br />}<br /></code></pre></blockquote>
<p>Une fois les droits nécessaires donnés au script, il ne reste plus qu'à le lancer en ligne de commande et à admirer le résultat.</p>
<p>Je vous laisse imaginer la puissance de ce script pour définir les goulots d'étranglement dans un système complexe, d'autant qu'il est possible de grandement l'améliorer...</p>
<p>En contrepartie, pour pouvoir être utilisé, ce qui nécessite un système d'exploitation qui le supporte, ce qui est uniquement le cas pour le moment de <a href="http://fr.wikipedia.org/wiki/Solaris_%28syst%C3%A8me_d%27exploitation%29">Solaris</a>, <a href="http://fr.wikipedia.org/wiki/Mac_OS_X">Mac OS X</a> et <a href="http://www.freebsd.org">FreeBSD</a>.</p>http://blog.mageekbox.net/?post/2010/06/16/DTrace-un-peu-plus-dans-le-d%C3%A9tail#comment-formhttp://blog.mageekbox.net/?feed/atom/comments/143