1 |
efrain |
1 |
<!DOCTYPE html>
|
|
|
2 |
<html lang="fr">
|
|
|
3 |
<head>
|
|
|
4 |
<meta charset="utf-8" />
|
|
|
5 |
<title>
|
|
|
6 |
Documentation XHProf (Brouillon)
|
|
|
7 |
</title>
|
|
|
8 |
<body>
|
|
|
9 |
<h3>Documentation XHProf (Brouillon)</h3>
|
|
|
10 |
|
|
|
11 |
<b>Sommaire</b>
|
|
|
12 |
<ol>
|
|
|
13 |
<li><a href="#introduction">Introduction</a></li>
|
|
|
14 |
|
|
|
15 |
<li><a href="#overview">Présentation</a></li>
|
|
|
16 |
|
|
|
17 |
<li><a href="#installation">Installer l’extension XHProf</a></li>
|
|
|
18 |
|
|
|
19 |
<li><a href="#using_extension">Profiler avec XHProf</a></li>
|
|
|
20 |
|
|
|
21 |
<li><a href="#ui_setup">Définir un environnement graphique pour XHProf</a></li>
|
|
|
22 |
|
|
|
23 |
<li><a href="#production_notes">Notes sur l’utilisation d’XHProf en production</a></li>
|
|
|
24 |
|
|
|
25 |
<li><a href="#sampling_mode">Mode aléatoire et léger</a>
|
|
|
26 |
|
|
|
27 |
<li><a href="#misc">Fonctionnalités supplémentaires</a></li>
|
|
|
28 |
|
|
|
29 |
<li><a href="#dependencies">Dépendences</a></li>
|
|
|
30 |
|
|
|
31 |
<li><a href="#credits">Remerciements</a></li>
|
|
|
32 |
</ol>
|
|
|
33 |
|
|
|
34 |
<ol>
|
|
|
35 |
<li><a name="introduction"><h2>Introduction</h2></a>
|
|
|
36 |
|
|
|
37 |
<p>XHProf est un outil de profilage hiérarchique pour PHP. Il relève
|
|
|
38 |
les appels au niveau des fonctions et mesure <a href="#inclusive">inclusivement</a> et
|
|
|
39 |
<a href="#exclusive">exclusivement</a> des métriques telles que le temps écoulé
|
|
|
40 |
la charge CPU ou l’usage de la mémoire. Un profil de fonction peut être divisé selon ses appelants, ou ses appelés. Le composant qui extrait les données brutes est écrit en C
|
|
|
41 |
et implémenté telle une extension PHP Zend.
|
|
|
42 |
<code><b>xhprof</b></code>. XHProf a une interface utilisateur simple en HTML, (écrite en PHP).
|
|
|
43 |
L’interface permet de visualiser et de partager facilement le résultat des profilages dans un navigateur.
|
|
|
44 |
Un rendu sous forme de graphique est également disponible.
|
|
|
45 |
|
|
|
46 |
<p>Les rapports fournis par XHProf permettent souvent de mieux comprendre
|
|
|
47 |
la structure du code qui est éxécuté.
|
|
|
48 |
Le rendu hiérarchique des rapports permet par exemple de déterminer
|
|
|
49 |
quelle chaîne d’appels mène à une fonction particulière.
|
|
|
50 |
|
|
|
51 |
<p>XHProf propose également de comparer deux runs (résultat de profilage)
|
|
|
52 |
pour analyser les différences ou aggréger les résultat de multiples runs afin
|
|
|
53 |
d’analyser des données consolidées.
|
|
|
54 |
Les comparaisons et aggrégations de données permettent surtout de visualiser des données plates
|
|
|
55 |
|
|
|
56 |
<p>XHProf est un outil de profilage très léger. Pendant la phase de collecte
|
|
|
57 |
Il garde une trace du nombre d’appels et des métriques inclusives viualisables en courbes dans le graphe d’appels dynamique d’un programme.
|
|
|
58 |
Il calcule les métriques exclusives dans la phase de rapport.
|
|
|
59 |
XHProf supporte les fonctions recursives en détectant les cycles dans la pile d’appels dès la capture des données et en utilisant un nom unique pour l’invocation principale.</p>
|
|
|
60 |
|
|
|
61 |
<p>La nature légère d’XHProf, ses performances et ses possibilités de consolidations de données
|
|
|
62 |
en font un outil taillé pour les environnements de production [Voir <a
|
|
|
63 |
href="#production_notes">les notes</a> sur l’usage en production.]
|
|
|
64 |
|
|
|
65 |
<ul>
|
|
|
66 |
<hr>
|
|
|
67 |
|
|
|
68 |
<p>XHProfLive (qui ne fait pas partie de ce kit open source), par exemple,
|
|
|
69 |
est un système de monitoring de performance utilsé chez Facebook et qui est bâti sur XHProf.
|
|
|
70 |
XHProfLive récupère en permanence les données de profilage en production en lançant XHProf sur un échantillon de pages
|
|
|
71 |
XHProfLive aggrège ensuite les données suivant des critères tels que le temps, type de pages, et peut aider à répondre à tout type de questions comme :
|
|
|
72 |
Quel est le profil de la pile d’appel pour une page spécifique ? Quel est le coût de la méthode "foo" dans toutes les pages, ou sur une page spécifique ? quelles fonctions ont régressé le plus depuis une heure, un jour pou un mois ? Quel est l’historique des tendances, des temps d’executions pour une page ou une fonction …
|
|
|
73 |
|
|
|
74 |
<hr>
|
|
|
75 |
</ul>
|
|
|
76 |
|
|
|
77 |
|
|
|
78 |
<p>Développé à l’origine par Facebook, XHProf est maintenant open source depuis mars 2009.</p>
|
|
|
79 |
|
|
|
80 |
|
|
|
81 |
</ul>
|
|
|
82 |
|
|
|
83 |
|
|
|
84 |
<li><a name="overview"><h2>Présentation</h2></a>
|
|
|
85 |
|
|
|
86 |
<p>XHProf offre:
|
|
|
87 |
|
|
|
88 |
<ul>
|
|
|
89 |
<li><b>Un rendu tabulaire</b> (<a href="sample-flat-view.jpg" >copie d’écran</a>)
|
|
|
90 |
|
|
|
91 |
<p>Un résumé des appels de fonctions avec des informations telles que le nombre d’appels,
|
|
|
92 |
inclusivement et exclusivement, les temps, la charge mémoire, et le temps processeur.
|
|
|
93 |
|
|
|
94 |
<p><li><b>Un rendu hiérarchique (Vue parent/enfant)</b>
|
|
|
95 |
(<a href="sample-parent-child-view.jpg" >copie d’écran</a>)
|
|
|
96 |
|
|
|
97 |
<p>Pour chaque fonction, il fournit le détail des appels et le temps par
|
|
|
98 |
parent (appelant) & enfant (appelé), tel que :
|
|
|
99 |
|
|
|
100 |
<ul>
|
|
|
101 |
|
|
|
102 |
<li> quelle fonctions appelle quelle fonction précisement et combien de fois ?
|
|
|
103 |
|
|
|
104 |
<li> Quelles fonctions font un appel particulier ?
|
|
|
105 |
|
|
|
106 |
<li> Le temps total passé dans une fonction appelé par un parent bien précis.
|
|
|
107 |
|
|
|
108 |
</ul>
|
|
|
109 |
|
|
|
110 |
<p><li><b>Comparateur de rapports</b>
|
|
|
111 |
|
|
|
112 |
<p>Vous pouvez comparer les données de deux appels à XHProf pour des raisons diverses;
|
|
|
113 |
Pour voir ce qui cause une régression entre une version du code et une autre,
|
|
|
114 |
Pour évaluer l’impact sur les performances d’une évolution dans le code …
|
|
|
115 |
|
|
|
116 |
<p>Une comparaison de rapport prends deux runs en entrée et produit à la fois des informations différencielles au niveau de la fonction, mais aussi des informations hiérarchiques (séparation des différences par fonction parente/enfant) pour chaque fonction.
|
|
|
117 |
|
|
|
118 |
<p>La vue tabulaire (<a href="sample-diff-report-flat-view.jpg"
|
|
|
119 |
>copie d’écran</a>) du rapport différentiel pointe les plus grosses améliorations et régressions.
|
|
|
120 |
|
|
|
121 |
<p>Cliquer sur un nom de fonction dans la bue tabulaire du rapport différentiel, mène à la vue hiérarchique
|
|
|
122 |
(ou vue parent/enfant) différentielle d’une fonction (<a href="sample-diff-report-parent-child-view.jpg"
|
|
|
123 |
>copie d’écran</a>). On peut ainsi avoir une séparation des différences par fonctions parent/enfant.
|
|
|
124 |
|
|
|
125 |
<p><li><b>Callgraph View</b> (<a href="sample-callgraph-image.jpg"
|
|
|
126 |
>copie d’écran</a>)
|
|
|
127 |
|
|
|
128 |
<p>Les données du rapport peuvent également être visualisées sous forme de graphique.
|
|
|
129 |
Cette vue permet de mettre en lumière les chemins crtiques du programme.
|
|
|
130 |
|
|
|
131 |
<p><li><b>Profilage mémoire</b>
|
|
|
132 |
|
|
|
133 |
<p>Le mode profilage mémoire d’XHProf aide à isoler les fonctions qui occupent trop de mémoire.
|
|
|
134 |
|
|
|
135 |
<p>On ne peut pas dire qu’XHProf trace exactement chaque opération
|
|
|
136 |
d’allocation/libération de mémoire, en effet il utilise un schéma simplistique;
|
|
|
137 |
Il trace les hausses et les baisse de besoin en mémoire allouée à PHP à chaque entré ou sortie de fonction.
|
|
|
138 |
Il trace aussi les hausses et baisses de pics mémoire alloués à chaque fonction PHP.
|
|
|
139 |
|
|
|
140 |
<li>XHProf trace les opération <code>include, include_once, require and
|
|
|
141 |
require_once</code> comme si c’était des fonctions. Le nom du fichier inclus est utilisé pour nommer <a
|
|
|
142 |
href="#include_funcs">"fausses" fonctions</a>.
|
|
|
143 |
|
|
|
144 |
|
|
|
145 |
</ul>
|
|
|
146 |
|
|
|
147 |
<a name="Terminology"></a><h2>Terminologie</h2>
|
|
|
148 |
<ol>
|
|
|
149 |
|
|
|
150 |
<a name="inclusive"></a><li><b>Temps inclusive (ou temps du sous-ensemble)</b>:
|
|
|
151 |
Inclus le temps passé dans la fonction et celui passé dans les fonctions descendantes (filles).
|
|
|
152 |
|
|
|
153 |
<a name="exclusive"></a><li><b>Temps exclusive (ou temps "propre")</b>: Mesure le temps passé dans la fonction elle-même et n’inclus pas le temps passé dans les fonctions descendantes.
|
|
|
154 |
|
|
|
155 |
<li><b>Wall Time</b>: Temps passé ou temps ressenti.
|
|
|
156 |
|
|
|
157 |
<li><b>CPU Time</b>: Charge CPU sur les process utilisateur + charge CPU sur les process noyaux
|
|
|
158 |
|
|
|
159 |
</ol>
|
|
|
160 |
<a name="Naming_convention_for_special_functions"></a><h2>Convention de nommage pour les fonctions spéciales</h2>
|
|
|
161 |
|
|
|
162 |
<ol>
|
|
|
163 |
<p><li><code><b>main()</b></code>: Une fonction fictive qui est à la racine de la pile d’appel.
|
|
|
164 |
|
|
|
165 |
<a name="include_funcs"></a>
|
|
|
166 |
<p><li><code><b>load::<filename></b></code>
|
|
|
167 |
et <code><b>run_init::<filename></b></code>:
|
|
|
168 |
|
|
|
169 |
<p>XHProf trace les appels <code>include/require</code> comme des appels de fonction.
|
|
|
170 |
|
|
|
171 |
<p>Par exemple, une inclusion <b>include "lib/common.php";</b> va donner deux entrées pour XHProf :
|
|
|
172 |
|
|
|
173 |
<ul>
|
|
|
174 |
|
|
|
175 |
<li> <code><b>load::lib/common.php</b></code> - Cela représente le travail fait par l’interpréteur pour charger et compiler le fichier.
|
|
|
176 |
[Note: Si vous utilisez un cache d’opcode PHP comme APC, alors la compilation intervient uniquement si le cahce est manquant dans APC.]
|
|
|
177 |
|
|
|
178 |
<li> <code><b>run_init::lib/common.php</b></code> - Cela répresente le code exécuté au niveau du fichier, soit le résultat de l’inclusion.
|
|
|
179 |
|
|
|
180 |
</ul>
|
|
|
181 |
|
|
|
182 |
<p><li><code><b>foo@<n></b></code>: Implique un appel récursif de <code>foo()</code>, ou <code><n></code> représente le niveau de récursion.
|
|
|
183 |
Cette récursion peut être directe comme <code>foo()</code> --> <code>foo()</code>), ou indirecte comme </code>foo()</code> --> <code>goo()</code> --> foo().
|
|
|
184 |
|
|
|
185 |
</ol>
|
|
|
186 |
|
|
|
187 |
|
|
|
188 |
<a name="Limitations"></a><h2>Limitations</h2>
|
|
|
189 |
|
|
|
190 |
<p>Un vrai profileur hiérarchique trace toute la pile d’appel pour chaque donnée., et est capables de répondre aux questions comme : Quel était le coût du 3e appel de foo(), ou quel était le coût de bar() quand il était appelé par a()->b()->bar()?
|
|
|
191 |
|
|
|
192 |
</p>
|
|
|
193 |
|
|
|
194 |
<p>XHProf garde une trace d’un seul niveau dans le contexte de l’appel et est seulement capable de répondre aux questions à propos
|
|
|
195 |
d’une fonction qui regarde un niveau en dessus ou en dessous.
|
|
|
196 |
Il appraît que dans la majorité des cas c’est bien suffisant.
|
|
|
197 |
</p>
|
|
|
198 |
|
|
|
199 |
<p>Pour mieux comprendre, regaredez l’exemple suivant :
|
|
|
200 |
</p>
|
|
|
201 |
|
|
|
202 |
<pre>
|
|
|
203 |
Vous avez:
|
|
|
204 |
1 appel de a() --> c()
|
|
|
205 |
1 appel de b() --> c()
|
|
|
206 |
50 appels de c() --> d()
|
|
|
207 |
</pre>
|
|
|
208 |
|
|
|
209 |
<p>Quand XHProf peut vous dire que d() a été appelé par c() 50 fois, il ne peut pas vous dire
|
|
|
210 |
combien d’appels dont dus à a() ou b().
|
|
|
211 |
[On peut imaginer que c’est peut être 25 pour a() et 25 pour b(), mais ce n’est pas nécéssairement vrai.]
|
|
|
212 |
</p>
|
|
|
213 |
|
|
|
214 |
<p>De toutes façons en pratique ce n’est pas vraiment une limitation.
|
|
|
215 |
</p>
|
|
|
216 |
|
|
|
217 |
<li><a name="installation"><h2>Installer l’extension XHProf</h2></a>
|
|
|
218 |
|
|
|
219 |
<p> L’extension se trouve dans le sous-répertoire "extension/".
|
|
|
220 |
|
|
|
221 |
<ul><hr>
|
|
|
222 |
|
|
|
223 |
<p><b>Note:</b> Le portage pour Windows n’est pas encore implémenté. Nous avons testé <code>XHProf</code> sur <b>Linux/FreeBSD</b>.
|
|
|
224 |
[NDT : Il existe un fork avec un portage Windows sur Github]
|
|
|
225 |
|
|
|
226 |
<p>La version 0.9.2 et les précédentes sont aussi censées fonctionner sur <b>Mac
|
|
|
227 |
OS</b>. [Cela a été testé sur Mac OS 10.5.]
|
|
|
228 |
|
|
|
229 |
<p><b>Note:</b> XHProf utilise les insctructions RDTSC (time stamp counter)
|
|
|
230 |
pour implémenter un compteur de temps vraiment bas niveau. C’est pourquoi actuellement <code>xhprof</code> fonctionne uniquement sur une architecture <b>x86</b>.
|
|
|
231 |
Aussi tant que les valeurs de RDTSC ne pourront pas être synchronisées entre plusieurs CPUs,
|
|
|
232 |
<code>xhprof</code> n’en utilisera qu’un seul lors du profilage.
|
|
|
233 |
|
|
|
234 |
<p>Le timer XHProf bzasé sur RDTSC ne fonctionen pas parfaitement si la techno
|
|
|
235 |
<b>SpeedStep</b> est activée. Cette technologie est disponible sur certains processeurs Intel.
|
|
|
236 |
[Note: Les Macs ont typiquement cette fonctionnalité d’activée par défaut, il faut donc la désactiver pour utiliser XHProf.]
|
|
|
237 |
|
|
|
238 |
<hr></ul>
|
|
|
239 |
|
|
|
240 |
<p> Les étapes suivantes sont prévues pour un environnement Linux/Unix.
|
|
|
241 |
|
|
|
242 |
|
|
|
243 |
<pre>
|
|
|
244 |
% cd <repertoire_source_xhprof>/extension/
|
|
|
245 |
% phpize
|
|
|
246 |
% ./configure --with-php-config=<chemin vers php-config>
|
|
|
247 |
% make
|
|
|
248 |
% make install
|
|
|
249 |
% make test
|
|
|
250 |
</pre>
|
|
|
251 |
|
|
|
252 |
|
|
|
253 |
<p><a name="ini_file"></a><b>php.ini file</b>: Vous pouvez mettre à jour votre fichier
|
|
|
254 |
php.ini file afin qu’il charge automatiquement votre extension en ajoutant le code suivant :
|
|
|
255 |
|
|
|
256 |
<pre>
|
|
|
257 |
[xhprof]
|
|
|
258 |
extension=xhprof.so
|
|
|
259 |
;
|
|
|
260 |
; répertoire utilisé par l’implémentation par défaut de l’interface iXHProfRuns
|
|
|
261 |
; (nommée, XHProfRuns_Default class) pour stocker les runs XHProf.
|
|
|
262 |
;
|
|
|
263 |
xhprof.output_dir=<repertoire_pour_stocker_les_runs_xhprof>
|
|
|
264 |
</pre>
|
|
|
265 |
|
|
|
266 |
|
|
|
267 |
<li><a name="using_extension"><h2>Profiler avec XHProf</h2></a>
|
|
|
268 |
|
|
|
269 |
<p>Test de génération de donées brutes avec l’exemple simple d’un programme tel que :
|
|
|
270 |
|
|
|
271 |
<ul>
|
|
|
272 |
<p><b>foo.php</b>
|
|
|
273 |
<pre>
|
|
|
274 |
<?php
|
|
|
275 |
|
|
|
276 |
function bar($x) {
|
|
|
277 |
if ($x > 0) {
|
|
|
278 |
bar($x - 1);
|
|
|
279 |
}
|
|
|
280 |
}
|
|
|
281 |
|
|
|
282 |
function foo() {
|
|
|
283 |
for ($idx = 0; $idx < 2; $idx++) {
|
|
|
284 |
bar($idx);
|
|
|
285 |
$x = strlen("abc");
|
|
|
286 |
}
|
|
|
287 |
}
|
|
|
288 |
|
|
|
289 |
// début du profileur
|
|
|
290 |
<b>xhprof_enable();</b>
|
|
|
291 |
|
|
|
292 |
// début du programme
|
|
|
293 |
foo();
|
|
|
294 |
|
|
|
295 |
// attêt du profileur
|
|
|
296 |
<b>$xhprof_data = xhprof_disable();</b>
|
|
|
297 |
|
|
|
298 |
// affichage des données de profilage brutes
|
|
|
299 |
print_r($xhprof_data);
|
|
|
300 |
</pre>
|
|
|
301 |
</ul>
|
|
|
302 |
|
|
|
303 |
<p><b>Lancez ce programme :</b>
|
|
|
304 |
|
|
|
305 |
<pre>
|
|
|
306 |
% php -dextension=xhprof.so foo.php
|
|
|
307 |
</pre>
|
|
|
308 |
|
|
|
309 |
<p><b>Vous devez avoir un résultat tel que :</b>
|
|
|
310 |
|
|
|
311 |
<pre>
|
|
|
312 |
Array
|
|
|
313 |
(
|
|
|
314 |
[foo==>bar] => Array
|
|
|
315 |
(
|
|
|
316 |
[ct] => 2 # 2 appels de bar() depuis foo()
|
|
|
317 |
[wt] => 27 # temps inclusif dans bar() quand il est appelé par foo()
|
|
|
318 |
)
|
|
|
319 |
|
|
|
320 |
[foo==>strlen] => Array
|
|
|
321 |
(
|
|
|
322 |
[ct] => 2
|
|
|
323 |
[wt] => 2
|
|
|
324 |
)
|
|
|
325 |
|
|
|
326 |
[bar==>bar@1] => Array # un appelrécursif à bar()
|
|
|
327 |
(
|
|
|
328 |
[ct] => 1
|
|
|
329 |
[wt] => 2
|
|
|
330 |
)
|
|
|
331 |
|
|
|
332 |
[main()==>foo] => Array
|
|
|
333 |
(
|
|
|
334 |
[ct] => 1
|
|
|
335 |
[wt] => 74
|
|
|
336 |
)
|
|
|
337 |
|
|
|
338 |
[main()==>xhprof_disable] => Array
|
|
|
339 |
(
|
|
|
340 |
[ct] => 1
|
|
|
341 |
[wt] => 0
|
|
|
342 |
)
|
|
|
343 |
|
|
|
344 |
[main()] => Array # fausse fonction représentant la racine
|
|
|
345 |
(
|
|
|
346 |
[ct] => 1
|
|
|
347 |
[wt] => 83
|
|
|
348 |
)
|
|
|
349 |
|
|
|
350 |
)
|
|
|
351 |
</pre>
|
|
|
352 |
|
|
|
353 |
<p><b>Note:</b> Les données brutes contienent uniquement les métriques inclusives.
|
|
|
354 |
Par exemple les données brutes du tableau de données temporelles represente les temps inclusifs en microsecondes.
|
|
|
355 |
Les temps exclusifs sont calculés pour chaque fonction lors de la phase d’analyse et de rapport.
|
|
|
356 |
|
|
|
357 |
<p><b>Note:</b> Par défault suelemnt le nombre d’appel & et le temps passé sont profilés.
|
|
|
358 |
Vous pouvez aussi profilerle temps CPU et/ou la charge mémoire. Remplacez,
|
|
|
359 |
|
|
|
360 |
<ul><pre>
|
|
|
361 |
<b>xhprof_enable();</b>
|
|
|
362 |
</pre></ul>
|
|
|
363 |
dans le programme précédent avec, par exemple :
|
|
|
364 |
<ul><pre>
|
|
|
365 |
<b>xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY)</b>;
|
|
|
366 |
</pre></ul>
|
|
|
367 |
|
|
|
368 |
<p><b>Vous aurez en sortie :</b>
|
|
|
369 |
|
|
|
370 |
<pre>
|
|
|
371 |
Array
|
|
|
372 |
(
|
|
|
373 |
[foo==>bar] => Array
|
|
|
374 |
(
|
|
|
375 |
[ct] => 2 # nombre d’appel à bar() depuis foo()
|
|
|
376 |
[wt] => 37 # tempas passé dans bar() quand appel de foo()
|
|
|
377 |
[cpu] => 0 # temps cpu time dans bar() quand appel de foo()
|
|
|
378 |
[mu] => 2208 # changement dans l’usage de la mémoire par PHP dans bar() quand appel de foo()
|
|
|
379 |
[pmu] => 0 # changement dans l’usage de pic mémoire par PHP pour bar() quand appel de foo()
|
|
|
380 |
)
|
|
|
381 |
|
|
|
382 |
[foo==>strlen] => Array
|
|
|
383 |
(
|
|
|
384 |
[ct] => 2
|
|
|
385 |
[wt] => 3
|
|
|
386 |
[cpu] => 0
|
|
|
387 |
[mu] => 624
|
|
|
388 |
[pmu] => 0
|
|
|
389 |
)
|
|
|
390 |
|
|
|
391 |
[bar==>bar@1] => Array
|
|
|
392 |
(
|
|
|
393 |
[ct] => 1
|
|
|
394 |
[wt] => 2
|
|
|
395 |
[cpu] => 0
|
|
|
396 |
[mu] => 856
|
|
|
397 |
[pmu] => 0
|
|
|
398 |
)
|
|
|
399 |
|
|
|
400 |
[main()==>foo] => Array
|
|
|
401 |
(
|
|
|
402 |
[ct] => 1
|
|
|
403 |
[wt] => 104
|
|
|
404 |
[cpu] => 0
|
|
|
405 |
[mu] => 4168
|
|
|
406 |
[pmu] => 0
|
|
|
407 |
)
|
|
|
408 |
|
|
|
409 |
[main()==>xhprof_disable] => Array
|
|
|
410 |
(
|
|
|
411 |
[ct] => 1
|
|
|
412 |
[wt] => 1
|
|
|
413 |
[cpu] => 0
|
|
|
414 |
[mu] => 344
|
|
|
415 |
[pmu] => 0
|
|
|
416 |
)
|
|
|
417 |
|
|
|
418 |
[main()] => Array
|
|
|
419 |
(
|
|
|
420 |
[ct] => 1
|
|
|
421 |
[wt] => 139
|
|
|
422 |
[cpu] => 0
|
|
|
423 |
[mu] => 5936
|
|
|
424 |
[pmu] => 0
|
|
|
425 |
)
|
|
|
426 |
|
|
|
427 |
)
|
|
|
428 |
</pre>
|
|
|
429 |
|
|
|
430 |
<p><b>Éviter les fonctions natives lors du profilage</b>
|
|
|
431 |
|
|
|
432 |
<p>Par défault les fonctions natives de PHP (comme <code>strlen</code>) sont profilées.
|
|
|
433 |
Si vous ne voulez pas les profiler (pour simplifier le résultat et la taille des données brutes générées),
|
|
|
434 |
Vous pouvez utiliser le drapeau <code><b>XHPROF_FLAGS_NO_BUILTINS</b></code> comme dans l’exemple ci-dessous :
|
|
|
435 |
|
|
|
436 |
<ul><pre>
|
|
|
437 |
// ne pas profiler les fonctions natives
|
|
|
438 |
<b>xhprof_enable(XHPROF_FLAGS_NO_BUILTINS)</b>;
|
|
|
439 |
</pre></ul>
|
|
|
440 |
|
|
|
441 |
|
|
|
442 |
<p><b>Ignorer des fonctions spécfiques lors du profilage (0.9.2 ou plus récent)</b>
|
|
|
443 |
|
|
|
444 |
<p>À partir de la version 0.9.2 d’XHProf, vous pouvez spécifier une liste de
|
|
|
445 |
fonctions à ignorer pendant le profilage. Cela vous permet de ne pas prendre en compte par exemple
|
|
|
446 |
des fonctions utilisées pour des appels indirects comme <code>call_user_func</code> et <code>call_user_func_array</code>.
|
|
|
447 |
Ces fonctions intermédiaires compliquent inutilement la hirarchie des appels et rendent plus ardue l’interprétation des rapports en brouillant les relations parent/enfant.
|
|
|
448 |
|
|
|
449 |
<p>Pour spécifier cette liste de fonctions à ignorer durant le profilage, il suffit d’utiliser le second paramètre (optionnel) de <code>xhprof_enable</code>.
|
|
|
450 |
Par exemple,
|
|
|
451 |
|
|
|
452 |
<pre>
|
|
|
453 |
<ul><pre>
|
|
|
454 |
<b>
|
|
|
455 |
// temps passé en profilage; ignore les appels de call_user_func* pendant le profilage
|
|
|
456 |
xhprof_enable(0,
|
|
|
457 |
array('ignored_functions' => array('call_user_func',
|
|
|
458 |
'call_user_func_array')));
|
|
|
459 |
</b>
|
|
|
460 |
or,
|
|
|
461 |
<b>
|
|
|
462 |
// tempas pasé en profilage + profilage mémoire; ignore call_user_func* durant le profilage
|
|
|
463 |
xhprof_enable(XHPROF_FLAGS_MEMORY,
|
|
|
464 |
array('ignored_functions' => array('call_user_func',
|
|
|
465 |
'call_user_func_array')));
|
|
|
466 |
</b>
|
|
|
467 |
</pre></ul>
|
|
|
468 |
|
|
|
469 |
|
|
|
470 |
</li>
|
|
|
471 |
|
|
|
472 |
<li><a name="ui_setup"><h2>Définir un environnement graphique pour XHProf</h2></a>
|
|
|
473 |
|
|
|
474 |
|
|
|
475 |
<ol>
|
|
|
476 |
|
|
|
477 |
<li><b>Structure de la source PHP</b>
|
|
|
478 |
<p>l’interface graphique d’XHProf est implémentée en PHP. Le code est divisé en deux sous-répertoires,
|
|
|
479 |
<code>xhprof_html/</code> and <code>xhprof_lib/</code>.
|
|
|
480 |
|
|
|
481 |
<p>Le répertoire <code>xhprof_html</code> contient les 3 pages PHP principales.
|
|
|
482 |
|
|
|
483 |
<ul>
|
|
|
484 |
<li><code>index.php</code>: Pour visualiser un run ou un différentiel entre deux runs.
|
|
|
485 |
<li><code>callgraph.php</code>: Pour visualiser sous la forme de graphique avec un rendu en image.
|
|
|
486 |
<li><code>typeahead.php</code>: Utilisé implicitement pour les fonctions de gestion de pile sur un rapport XHProf.
|
|
|
487 |
</ul>
|
|
|
488 |
|
|
|
489 |
<p>Le répertoire <code>xhprof_lib</code> contient le code pour l’analyse et l’affichage.
|
|
|
490 |
(calcul sur les informations de profilage, calcul des différentiels, aggrégation de données, etc.).
|
|
|
491 |
|
|
|
492 |
<li><p><b>Configuration du server web : </b> Vous devez vous assurer que le répertoire
|
|
|
493 |
<code>xhprof_html/</code> est accessible depuis le serveur web, et qu’il est configuré pour éxécuter des scripts PHP.
|
|
|
494 |
|
|
|
495 |
<li><p><b>Gérer les runs XHProf</b>
|
|
|
496 |
|
|
|
497 |
<p>Les clients web ont une certaine souplesse dans la manière de sauvegarder les données brutes fournies par XHProf.
|
|
|
498 |
XHProf expose une interface utilisateur nommée iXHProfRuns (voir xhprof_lib/utils/xhprof_runs.php) que les clients peuvent implémenter.
|
|
|
499 |
Cela permet aux clients de préciser comment afficher les donées des runs.
|
|
|
500 |
|
|
|
501 |
<p>L’interface utilisateur d’XHProf fournit une implementation par défaut nommée,
|
|
|
502 |
"XHProfRuns_Default" (aussi dans xhprof_lib/utils/xhprof_runs.php).
|
|
|
503 |
L’implementation par d"faut stocke les runs dans le répertoire définit par le paramètre INI :
|
|
|
504 |
<a href="#ini_file"><b>xhprof.output_dir</b></a>.
|
|
|
505 |
|
|
|
506 |
<p>Un run XHProf doit être définit de manière unique par un espace de nom et un identifiant de run.
|
|
|
507 |
|
|
|
508 |
<p><b>a) Sauver les données XHProf de façon persistente</b> :
|
|
|
509 |
|
|
|
510 |
<p>Soit si vous utilisez l’interface par défaut,
|
|
|
511 |
<code><b>XHProfRuns_Default</b></code> qui implémente
|
|
|
512 |
<code><b>iXHProfRuns</b></code>, Un run XHProf sauvegardé ressemble au code suivant :
|
|
|
513 |
|
|
|
514 |
|
|
|
515 |
<pre>
|
|
|
516 |
// début du profilage
|
|
|
517 |
xhprof_enable();
|
|
|
518 |
|
|
|
519 |
// lancement du programme
|
|
|
520 |
...
|
|
|
521 |
|
|
|
522 |
// fin du profilage
|
|
|
523 |
$xhprof_data = xhprof_disable();
|
|
|
524 |
|
|
|
525 |
//
|
|
|
526 |
// Sauvegarde du run XHProf
|
|
|
527 |
// en utilisant l’implementation par défaut de iXHProfRuns.
|
|
|
528 |
//
|
|
|
529 |
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
|
|
|
530 |
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";
|
|
|
531 |
|
|
|
532 |
$xhprof_runs = new <b>XHProfRuns_Default()</b>;
|
|
|
533 |
|
|
|
534 |
// sauvegarde du run avec l’espace de nom "xhprof_foo".
|
|
|
535 |
//
|
|
|
536 |
// **NOTE**:
|
|
|
537 |
// par défault save_run() va automatiquement générer un identifiant de run
|
|
|
538 |
// unique. [Vous pouvez surcharger cette donnée en passant l’identifiant en paramètre optionnel
|
|
|
539 |
// à la méthode save_run().]
|
|
|
540 |
//
|
|
|
541 |
<b>$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");</b>
|
|
|
542 |
|
|
|
543 |
echo "---------------\n".
|
|
|
544 |
"En partant du principe que vous avez parametré l’interface utilisateur http \n".
|
|
|
545 |
"XHProf, vous pouvez visualiser les runs avec l’adresse : \n".
|
|
|
546 |
"http://<adresse-interface-utilisateur-xhprof>/index.php?run=$run_id&source=xhprof_foo\n".
|
|
|
547 |
"---------------\n";
|
|
|
548 |
|
|
|
549 |
</pre>
|
|
|
550 |
|
|
|
551 |
<p>La suite permet de sauvegarder le run sous forme d’un fichier dans le répertoire spécifié
|
|
|
552 |
par le paramètre ini <code><b>xhprof.output_dir</b></code>. Le nom du fichier doit être de la forme
|
|
|
553 |
<b><code>49bafaa3a3f66.xhprof_foo</code></b>; Les deux parties du nom sont formées par l’identifiant du run
|
|
|
554 |
("49bafaa3a3f66") et l’espace de nom ("xhprof_foo"). [Si vous souhaitez créer un identifiant de run vous-même
|
|
|
555 |
(comme une sequence de base de données, ou un timestamp), vous pouvez explicitementpasser l’identifiant
|
|
|
556 |
du run à la méthode <code>save_run</code>.
|
|
|
557 |
|
|
|
558 |
<p><b>b) En utilisant votre propre implementation d’iXHProfRuns</b>
|
|
|
559 |
|
|
|
560 |
<p> Si vous décidez de stocker différement les runs XHProf
|
|
|
561 |
(soit dans un format compressé, dans une base de données,
|
|
|
562 |
etc.), vous aurez besoin d’implémenter une classe qui implémente l’interface
|
|
|
563 |
iXHProfRuns().
|
|
|
564 |
|
|
|
565 |
<p> Vous devrez également modifier les 3 pages PHP d’entrée (index.php,
|
|
|
566 |
callgraph.php, typeahead.php) dans le répertoire "xhprof_html/" pour utiliser la
|
|
|
567 |
nouvelle interface au lieu de celle par défaut (<code>XHProfRuns_Default</code>),
|
|
|
568 |
changez cette ligne dans les 3 fichier.
|
|
|
569 |
|
|
|
570 |
<pre>
|
|
|
571 |
$xhprof_runs_impl = new XHProfRuns_Default();
|
|
|
572 |
</pre>
|
|
|
573 |
|
|
|
574 |
<p>Vous aurez aussi besoin d’inclure le fichier qui implémente votre classe dans les fichiers cités.
|
|
|
575 |
|
|
|
576 |
<li><p><b>Acceéder aux runs depuis l’interface utilisateur</b>
|
|
|
577 |
|
|
|
578 |
<p><b>a) Voir un rapport simple</b>
|
|
|
579 |
|
|
|
580 |
<p>Pour voir un rapport avec l’identifiant <run_id> et l’espace de nom
|
|
|
581 |
<namespace> utilisez une url de la forme :
|
|
|
582 |
|
|
|
583 |
<p><code>
|
|
|
584 |
http://<adresse-interface-utilisateur-xhprof>/index.php?run=<run_id>&source=<namespace>
|
|
|
585 |
</code>
|
|
|
586 |
|
|
|
587 |
<p>Par example,
|
|
|
588 |
<p><code>
|
|
|
589 |
http://<adresse-interface-utilisateur-xhprof>/index.php?run=49bafaa3a3f66&source=xhprof_foo
|
|
|
590 |
</code>
|
|
|
591 |
|
|
|
592 |
<p><b>b) Voir un rapport différentiel</b>
|
|
|
593 |
|
|
|
594 |
<p>Pour voir un rapport avec les identifiants <run_id1> et
|
|
|
595 |
<run_id2> et l’espace de nom <namespace> utilisez une url de la forme :
|
|
|
596 |
|
|
|
597 |
<p><code>
|
|
|
598 |
http://<adresse-interface-utilisateur-xhprof>/index.php?<b>run1=<run_id1>&run2=<run_id2></b>&source=<namespace>
|
|
|
599 |
</code>
|
|
|
600 |
|
|
|
601 |
<p><b>c) Voir un rapport d’aggrégation</b>
|
|
|
602 |
|
|
|
603 |
<p>Vous pouvez aussi spécifier un ensemble de runspour lesquels vous souhaitez un rapport d’aggrégation.
|
|
|
604 |
|
|
|
605 |
<p>Si vous avez trois runs XHProf avec les identifiants 1, 2 & 3 pour l’espace de noms
|
|
|
606 |
"benchmark". Pour voir l’aggrégation de ces trois runs :
|
|
|
607 |
|
|
|
608 |
<ul><p><code>
|
|
|
609 |
http://<adresse-interface-utilisateur-xhprof>/index.php?<b>run=1,2,3</b>&source=benchmark
|
|
|
610 |
</code></p></ul>
|
|
|
611 |
|
|
|
612 |
<p><b>Aggrégations pondérées</b>: En supposant que les trois runs
|
|
|
613 |
correspondent à trois types de programmes p1.php, p2.php and p3.php
|
|
|
614 |
qui occupent chacun respectivement 20%, 30% et 50%. Pour voir un rapport d’aggrégation
|
|
|
615 |
pondéré par les poids des runs :
|
|
|
616 |
|
|
|
617 |
<ul><p><code>
|
|
|
618 |
http://<adresse-interface-utilisateur-xhprof>/index.php?<b>run=1,2,3&wts=20,30,50</b>&source=benchmark
|
|
|
619 |
</code></p></ul>
|
|
|
620 |
|
|
|
621 |
</ol>
|
|
|
622 |
|
|
|
623 |
<li><a name="production_notes"><h2>Notes sur l’utilisation d’XHProf en production</h2></a>
|
|
|
624 |
|
|
|
625 |
<p>Quelques observations qui peuvent faire varier votre expérience :
|
|
|
626 |
|
|
|
627 |
<ul>
|
|
|
628 |
|
|
|
629 |
<li>Le timer CPU (getrusage) sur Linux peut avoir des dépassements de capacité. Il a également un rendu granuleux
|
|
|
630 |
(Une précision à la milliseconde plutôt qu’à la microseconde) pour être efficace au niveau des méthodes.
|
|
|
631 |
En conséquence, les valeurs rapportées en utilisant le mode XHPROF_FLAGS_CPU on tendance à être plus élevés.
|
|
|
632 |
|
|
|
633 |
<p>Nous recommandons d’utiliser le mode de profilage "temps passé" + "memoire" en production.
|
|
|
634 |
[Note: Le surplus de temps passé par le mode de profilage mémoire est non significatif.]
|
|
|
635 |
|
|
|
636 |
<p><ul><pre><b>
|
|
|
637 |
// profilage du temps passé (par défault) + profilage mémoire
|
|
|
638 |
xhprof_enable(XHPROF_FLAGS_MEMORY);
|
|
|
639 |
</b></pre>
|
|
|
640 |
</ul></p>
|
|
|
641 |
|
|
|
642 |
|
|
|
643 |
<li>Profiler une plage aléatoire de pages/requêtes est efficace pour récupérer des données représentatives
|
|
|
644 |
de votre environnement de production.
|
|
|
645 |
|
|
|
646 |
<p>Pour profiler 1/10000 de vos requêtes, définissez le début du profilage avec un code dans l’esprit de celui-ci :
|
|
|
647 |
|
|
|
648 |
<p><ul><pre><code>
|
|
|
649 |
if (mt_rand(1, 10000) == 1) {
|
|
|
650 |
xhprof_enable(XHPROF_FLAGS_MEMORY);
|
|
|
651 |
$xhprof_on = true;
|
|
|
652 |
}
|
|
|
653 |
</code></pre></ul></p>
|
|
|
654 |
|
|
|
655 |
<p>À la fin de la requête (ou dans une fonction de finalisation de la requête), vous pouvez faire quelque chose comme :
|
|
|
656 |
|
|
|
657 |
<p><ul><pre><code>
|
|
|
658 |
if ($xhprof_on) {
|
|
|
659 |
// fin du profilage
|
|
|
660 |
$xhprof_data = xhprof_disable();
|
|
|
661 |
|
|
|
662 |
// sauvegarde $xhprof_data quelquepart (base de données centralisée …)
|
|
|
663 |
...
|
|
|
664 |
}
|
|
|
665 |
</code></pre></ul></p>
|
|
|
666 |
|
|
|
667 |
<p> Vous pouvez alors récupérer et aggréger ces profilages par horaire
|
|
|
668 |
(par exemple 5 minutes, par jour, par jour …), par page ou type de requête, ou n’importe quel
|
|
|
669 |
paramètre utilisé par <a href="#xhprof_aggregate_runs"><code><b>xhprof_aggregate_runs()</b></code></a>.
|
|
|
670 |
|
|
|
671 |
</ul>
|
|
|
672 |
|
|
|
673 |
<li><a name="sampling_mode"><h2>Mode d’échantillonage léger</h2></a>
|
|
|
674 |
|
|
|
675 |
<p>L’extension XHProf propose aussi un <b>mode très léger d’échantillonage</b>.
|
|
|
676 |
L’intervalle est de 0,1 seconde. Les échantillons enregistrent l’ensemble des données.
|
|
|
677 |
Ce mode peut être très utile pour avoir un impact le plus négligeable possible, et permettre
|
|
|
678 |
Le mode sample peut être utile si vous désirez un moyen avec peu de dépassement de faire de la surveillance de performances et des diagnostics.
|
|
|
679 |
|
|
|
680 |
<p>Les très pertinentes fonctions utilisées par l’extension pour utiliser le mode
|
|
|
681 |
d’échantillonage sont <code><b>xhprof_sample_enable()</b></code> et <code><b>xhprof_sample_disable()</b></code>.
|
|
|
682 |
|
|
|
683 |
<p>[<b>TBD</b>: Documentation plus détaillée pour le mode d’échantillonage.]
|
|
|
684 |
|
|
|
685 |
<li><a name="misc"><h2>Fonctionnalités supplémentaires</h2></a></li>
|
|
|
686 |
|
|
|
687 |
<p>Le fichier <code><b>XHProf_lib/utils/xhprof_lib.php</b></code> contient
|
|
|
688 |
des librairies de fonctions additionellesqui peuvent être utilisées pour manipuler
|
|
|
689 |
et aggréger les runs XHProf.
|
|
|
690 |
|
|
|
691 |
<p>Par exemple:
|
|
|
692 |
|
|
|
693 |
<ul>
|
|
|
694 |
|
|
|
695 |
<a name="xhprof_aggregate_runs"></a>
|
|
|
696 |
<p><li><code><b>xhprof_aggregate_runs()</b></code>:
|
|
|
697 |
peut être utilisé pour aggréger de multiples runs XHProf runs dans un seul run.
|
|
|
698 |
Cela peut être très utile pour fabriquer un outil de monitoring utilisant XHProf et à l’échelle voulue.
|
|
|
699 |
[Par exemple, vous pouvez mixer des runs XHProf issus périodiquement
|
|
|
700 |
d’échantillonage de la production pour générer des rapport journalier.]
|
|
|
701 |
|
|
|
702 |
<p><li><code><b>xhprof_prune_run()</b></code>: Aggréger une grande quantité de runs
|
|
|
703 |
(particulièrement si ils correspondent à des zones différentes du programme) peut créer un rendu
|
|
|
704 |
graphique beaucoup trop gros. Vous pouvez donc utiliser la fonction <code>xhprof_prune_run</code>
|
|
|
705 |
élaguer les données à afficher. En supprimant des branches qui compte pour une partie négligeable du temps passé.
|
|
|
706 |
|
|
|
707 |
</ul>
|
|
|
708 |
|
|
|
709 |
<ol>
|
|
|
710 |
|
|
|
711 |
</ol>
|
|
|
712 |
|
|
|
713 |
<li><a name="dependencies"><h2>Dependances</h2></a></li>
|
|
|
714 |
|
|
|
715 |
<ul>
|
|
|
716 |
<li><b>JQuery Javascript</b>: Pour les bulles d’aides et les noms de fonctions de pile,
|
|
|
717 |
nous utilisons la librairie Javascript, JQuery. JQuery est disponible sous les licences MIT et GPL
|
|
|
718 |
(http://docs.jquery.com/Licensing). Ce code JQuery, utilisé par XHProf, se trouve dans le
|
|
|
719 |
sous répertoire <code>xhprof_html/jquery</code>.
|
|
|
720 |
|
|
|
721 |
<li><b>dot (utilitaire de génération d’image):</b> Le fonctionnalité de rendu graphique
|
|
|
722 |
([View Callgraph]) est présente grâce à la présence de Graphviz "dot" dans votre path.
|
|
|
723 |
"dot" est un utilitaire de dessin et de gén"ration d’image.
|
|
|
724 |
|
|
|
725 |
</ul>
|
|
|
726 |
<li><a name="credits"><h2>Remerciements</h2></a>
|
|
|
727 |
|
|
|
728 |
<p>Le rendu HTML et l’interface de navigation pour consulter les résultat du profilage sont inspirés par un outil similaire
|
|
|
729 |
qui existe pour les procédures stockées PL/SQL d’Oracle. Mais c’est là que la comparaison s’arrête;
|
|
|
730 |
Le fonctionnement interne du profileur étant assez différent
|
|
|
731 |
|
|
|
732 |
[NDT : Merci à Rudy Rigot (@rudyrigot) pour sa relecture attentive ]
|
|
|
733 |
</li>
|
|
|
734 |
|
|
|
735 |
</ol>
|
|
|
736 |
|
|
|
737 |
</body>
|
|
|
738 |
</html>
|