MDL-76397 lib: xhprof upgraded to 2.3.9

This commit is contained in:
Stevani Andolo 2023-03-22 09:51:45 +08:00
parent 2e1c6fd43e
commit ae0ea56f25
14 changed files with 1574 additions and 54 deletions

View file

@ -260,7 +260,7 @@ All rights reserved.</copyright>
<location>xhprof</location> <location>xhprof</location>
<name>XHProf</name> <name>XHProf</name>
<description>A Hierarchical Profiler for PHP.</description> <description>A Hierarchical Profiler for PHP.</description>
<version>2.3.5</version> <version>2.3.8</version>
<license>Apache</license> <license>Apache</license>
<licenseversion>2.0</licenseversion> <licenseversion>2.0</licenseversion>
<repository>https://github.com/longxinH/xhprof</repository> <repository>https://github.com/longxinH/xhprof</repository>

View file

@ -1,17 +1,17 @@
# xhprof for PHP7 # xhprof for PHP7 and PHP8
[![Build Status](https://travis-ci.com/longxinH/xhprof.svg?branch=master)](https://travis-ci.com/longxinH/xhprof) [![Build status](https://ci.appveyor.com/api/projects/status/dornfeel5yutaxte/branch/master?svg=true)](https://ci.appveyor.com/project/longxinH/xhprof/branch/master) [![Build Status](https://travis-ci.com/longxinH/xhprof.svg?branch=master)](https://app.travis-ci.com/github/longxinH/xhprof) [![Build status](https://ci.appveyor.com/api/projects/status/dornfeel5yutaxte/branch/master?svg=true)](https://ci.appveyor.com/project/longxinH/xhprof/branch/master)
XHProf is a function-level hierarchical profiler for PHP and has a simple HTML based navigational interface. The raw data collection component is implemented in C (as a PHP extension). The reporting/UI layer is all in PHP. It is capable of reporting function-level inclusive and exclusive wall times, memory usage, CPU times and number of calls for each function. Additionally, it supports ability to compare two runs (hierarchical DIFF reports), or aggregate results from multiple runs. XHProf is a function-level hierarchical profiler for PHP and has a simple HTML based navigational interface. The raw data collection component is implemented in C (as a PHP extension). The reporting/UI layer is all in PHP. It is capable of reporting function-level inclusive and exclusive wall times, memory usage, CPU times and number of calls for each function. Additionally, it supports ability to compare two runs (hierarchical DIFF reports), or aggregate results from multiple runs.
This version supports PHP7 This version supports PHP7 and PHP8
# PHP Version # PHP Version
- 7.0
- 7.1
- 7.2 - 7.2
- 7.3 - 7.3
- 7.4 - 7.4
- 8.0 - 8.0
- 8.1
- 8.2
# Installation # Installation
``` ```

View file

@ -29,15 +29,6 @@
* @author Changhao Jiang (cjiang@facebook.com) * @author Changhao Jiang (cjiang@facebook.com)
*/ */
// Start moodle modification: moodleize this script.
require_once(dirname(dirname(dirname(dirname(__FILE__)))).'/config.php');
require_once($CFG->libdir . '/xhprof/xhprof_moodle.php');
require_login();
require_capability('moodle/site:config', context_system::instance());
raise_memory_limit(MEMORY_HUGE);
\core\session\manager::write_close();
// End moodle modification.
// by default assume that xhprof_html & xhprof_lib directories // by default assume that xhprof_html & xhprof_lib directories
// are at the same level. // are at the same level.
$GLOBALS['XHPROF_LIB_ROOT'] = dirname(__FILE__) . '/../xhprof_lib'; $GLOBALS['XHPROF_LIB_ROOT'] = dirname(__FILE__) . '/../xhprof_lib';
@ -87,10 +78,7 @@ if (!array_key_exists($type, $xhprof_legal_image_types)) {
$type = $params['type'][1]; // default image type. $type = $params['type'][1]; // default image type.
} }
// Start moodle modification: use own XHProfRuns implementation. $xhprof_runs_impl = new XHProfRuns_Default();
// $xhprof_runs_impl = new XHProfRuns_Default();
$xhprof_runs_impl = new moodle_xhprofrun();
// End moodle modification.
if (!empty($run)) { if (!empty($run)) {
// single run call graph image generation // single run call graph image generation

View file

@ -13,12 +13,6 @@
* limitations under the License. * limitations under the License.
*/ */
/* Start moodle modification: add basic, smaller, font specs */
body, p, table, li {
font: normal normal normal 13px/1.231 arial, helvetica, clean, sans-serif;
}
/* End moodle modification */
td.sorted { td.sorted {
color:#0000FF; color:#0000FF;
} }

View file

@ -0,0 +1,738 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<title>
Documentation XHProf (Brouillon)
</title>
<body>
<h3>Documentation XHProf (Brouillon)</h3>
<b>Sommaire</b>
<ol>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#overview">Présentation</a></li>
<li><a href="#installation">Installer lextension XHProf</a></li>
<li><a href="#using_extension">Profiler avec XHProf</a></li>
<li><a href="#ui_setup">Définir un environnement graphique pour XHProf</a></li>
<li><a href="#production_notes">Notes sur lutilisation dXHProf en production</a></li>
<li><a href="#sampling_mode">Mode aléatoire et léger</a>
<li><a href="#misc">Fonctionnalités supplémentaires</a></li>
<li><a href="#dependencies">Dépendences</a></li>
<li><a href="#credits">Remerciements</a></li>
</ol>
<ol>
<li><a name="introduction"><h2>Introduction</h2></a>
<p>XHProf est un outil de profilage hiérarchique pour PHP. Il relève
les appels au niveau des fonctions et mesure <a href="#inclusive">inclusivement</a> et
<a href="#exclusive">exclusivement</a> des métriques telles que le temps écoulé
la charge CPU ou lusage 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
et implémenté telle une extension PHP Zend.
<code><b>xhprof</b></code>. XHProf a une interface utilisateur simple en HTML, (écrite en PHP).
Linterface permet de visualiser et de partager facilement le résultat des profilages dans un navigateur.
Un rendu sous forme de graphique est également disponible.
<p>Les rapports fournis par XHProf permettent souvent de mieux comprendre
la structure du code qui est éxécuté.
Le rendu hiérarchique des rapports permet par exemple de déterminer
quelle chaîne dappels mène à une fonction particulière.
<p>XHProf propose également de comparer deux runs (résultat de profilage)
pour analyser les différences ou aggréger les résultat de multiples runs afin
danalyser des données consolidées.
Les comparaisons et aggrégations de données permettent surtout de visualiser des données plates
<p>XHProf est un outil de profilage très léger. Pendant la phase de collecte
Il garde une trace du nombre dappels et des métriques inclusives viualisables en courbes dans le graphe dappels dynamique dun programme.
Il calcule les métriques exclusives dans la phase de rapport.
XHProf supporte les fonctions recursives en détectant les cycles dans la pile dappels dès la capture des données et en utilisant un nom unique pour linvocation principale.</p>
<p>La nature légère dXHProf, ses performances et ses possibilités de consolidations de données
en font un outil taillé pour les environnements de production [Voir <a
href="#production_notes">les notes</a> sur lusage en production.]
<ul>
<hr>
<p>XHProfLive (qui ne fait pas partie de ce kit open source), par exemple,
est un système de monitoring de performance utilsé chez Facebook et qui est bâti sur XHProf.
XHProfLive récupère en permanence les données de profilage en production en lançant XHProf sur un échantillon de pages
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 :
Quel est le profil de la pile dappel 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 lhistorique des tendances, des temps dexecutions pour une page ou une fonction …
<hr>
</ul>
<p>Développé à lorigine par Facebook, XHProf est maintenant open source depuis mars 2009.</p>
</ul>
<li><a name="overview"><h2>Présentation</h2></a>
<p>XHProf offre:
<ul>
<li><b>Un rendu tabulaire</b> (<a href="sample-flat-view.jpg" >copie décran</a>)
<p>Un résumé des appels de fonctions avec des informations telles que le nombre dappels,
inclusivement et exclusivement, les temps, la charge mémoire, et le temps processeur.
<p><li><b>Un rendu hiérarchique (Vue parent/enfant)</b>
(<a href="sample-parent-child-view.jpg" >copie décran</a>)
<p>Pour chaque fonction, il fournit le détail des appels et le temps par
parent (appelant) & enfant (appelé), tel que :
<ul>
<li> quelle fonctions appelle quelle fonction précisement et combien de fois ?
<li> Quelles fonctions font un appel particulier ?
<li> Le temps total passé dans une fonction appelé par un parent bien précis.
</ul>
<p><li><b>Comparateur de rapports</b>
<p>Vous pouvez comparer les données de deux appels à XHProf pour des raisons diverses;
Pour voir ce qui cause une régression entre une version du code et une autre,
Pour évaluer limpact sur les performances dune évolution dans le code …
<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.
<p>La vue tabulaire (<a href="sample-diff-report-flat-view.jpg"
>copie décran</a>) du rapport différentiel pointe les plus grosses améliorations et régressions.
<p>Cliquer sur un nom de fonction dans la bue tabulaire du rapport différentiel, mène à la vue hiérarchique
(ou vue parent/enfant) différentielle dune fonction (<a href="sample-diff-report-parent-child-view.jpg"
>copie décran</a>). On peut ainsi avoir une séparation des différences par fonctions parent/enfant.
<p><li><b>Callgraph View</b> (<a href="sample-callgraph-image.jpg"
>copie décran</a>)
<p>Les données du rapport peuvent également être visualisées sous forme de graphique.
Cette vue permet de mettre en lumière les chemins crtiques du programme.
<p><li><b>Profilage mémoire</b>
<p>Le mode profilage mémoire dXHProf aide à isoler les fonctions qui occupent trop de mémoire.
<p>On ne peut pas dire quXHProf trace exactement chaque opération
dallocation/libération de mémoire, en effet il utilise un schéma simplistique;
Il trace les hausses et les baisse de besoin en mémoire allouée à PHP à chaque entré ou sortie de fonction.
Il trace aussi les hausses et baisses de pics mémoire alloués à chaque fonction PHP.
<li>XHProf trace les opération <code>include, include_once, require and
require_once</code> comme si cétait des fonctions. Le nom du fichier inclus est utilisé pour nommer <a
href="#include_funcs">"fausses" fonctions</a>.
</ul>
<a name="Terminology"></a><h2>Terminologie</h2>
<ol>
<a name="inclusive"></a><li><b>Temps inclusive (ou temps du sous-ensemble)</b>:
Inclus le temps passé dans la fonction et celui passé dans les fonctions descendantes (filles).
<a name="exclusive"></a><li><b>Temps exclusive (ou temps "propre")</b>: Mesure le temps passé dans la fonction elle-même et ninclus pas le temps passé dans les fonctions descendantes.
<li><b>Wall Time</b>: Temps passé ou temps ressenti.
<li><b>CPU Time</b>: Charge CPU sur les process utilisateur + charge CPU sur les process noyaux
</ol>
<a name="Naming_convention_for_special_functions"></a><h2>Convention de nommage pour les fonctions spéciales</h2>
<ol>
<p><li><code><b>main()</b></code>: Une fonction fictive qui est à la racine de la pile dappel.
<a name="include_funcs"></a>
<p><li><code><b>load::&lt;filename&gt;</b></code>
et <code><b>run_init::&lt;filename&gt;</b></code>:
<p>XHProf trace les appels <code>include/require</code> comme des appels de fonction.
<p>Par exemple, une inclusion <b>include "lib/common.php";</b> va donner deux entrées pour XHProf :
<ul>
<li> <code><b>load::lib/common.php</b></code> - Cela représente le travail fait par linterpréteur pour charger et compiler le fichier.
[Note: Si vous utilisez un cache dopcode PHP comme APC, alors la compilation intervient uniquement si le cahce est manquant dans APC.]
<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 linclusion.
</ul>
<p><li><code><b>foo@&lt;n&gt;</b></code>: Implique un appel récursif de <code>foo()</code>, ou <code>&lt;n&gt;</code> représente le niveau de récursion.
Cette récursion peut être directe comme <code>foo()</code> --&gt; <code>foo()</code>), ou indirecte comme </code>foo()</code> --&gt; <code>goo()</code> --&gt; foo().
</ol>
<a name="Limitations"></a><h2>Limitations</h2>
<p>Un vrai profileur hiérarchique trace toute la pile dappel 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()-&gt;b()-&gt;bar()?
</p>
<p>XHProf garde une trace dun seul niveau dans le contexte de lappel et est seulement capable de répondre aux questions à propos
dune fonction qui regarde un niveau en dessus ou en dessous.
Il appraît que dans la majorité des cas cest bien suffisant.
</p>
<p>Pour mieux comprendre, regaredez lexemple suivant :
</p>
<pre>
Vous avez:
1 appel de a() --&gt; c()
1 appel de b() --&gt; c()
50 appels de c() --&gt; d()
</pre>
<p>Quand XHProf peut vous dire que d() a été appelé par c() 50 fois, il ne peut pas vous dire
combien dappels dont dus à a() ou b().
[On peut imaginer que cest peut être 25 pour a() et 25 pour b(), mais ce nest pas nécéssairement vrai.]
</p>
<p>De toutes façons en pratique ce nest pas vraiment une limitation.
</p>
<li><a name="installation"><h2>Installer lextension XHProf</h2></a>
<p> Lextension se trouve dans le sous-répertoire "extension/".
<ul><hr>
<p><b>Note:</b> Le portage pour Windows nest pas encore implémenté. Nous avons testé <code>XHProf</code> sur <b>Linux/FreeBSD</b>.
[NDT : Il existe un fork avec un portage Windows sur Github]
<p>La version 0.9.2 et les précédentes sont aussi censées fonctionner sur <b>Mac
OS</b>. [Cela a été testé sur Mac OS 10.5.]
<p><b>Note:</b> XHProf utilise les insctructions RDTSC (time stamp counter)
pour implémenter un compteur de temps vraiment bas niveau. Cest pourquoi actuellement <code>xhprof</code> fonctionne uniquement sur une architecture <b>x86</b>.
Aussi tant que les valeurs de RDTSC ne pourront pas être synchronisées entre plusieurs CPUs,
<code>xhprof</code> nen utilisera quun seul lors du profilage.
<p>Le timer XHProf bzasé sur RDTSC ne fonctionen pas parfaitement si la techno
<b>SpeedStep</b> est activée. Cette technologie est disponible sur certains processeurs Intel.
[Note: Les Macs ont typiquement cette fonctionnalité dactivée par défaut, il faut donc la désactiver pour utiliser XHProf.]
<hr></ul>
<p> Les étapes suivantes sont prévues pour un environnement Linux/Unix.
<pre>
% cd &lt;repertoire_source_xhprof&gt;/extension/
% phpize
% ./configure --with-php-config=&lt;chemin vers php-config&gt;
% make
% make install
% make test
</pre>
<p><a name="ini_file"></a><b>php.ini file</b>: Vous pouvez mettre à jour votre fichier
php.ini file afin quil charge automatiquement votre extension en ajoutant le code suivant :
<pre>
[xhprof]
extension=xhprof.so
;
; répertoire utilisé par limplémentation par défaut de linterface iXHProfRuns
; (nommée, XHProfRuns_Default class) pour stocker les runs XHProf.
;
xhprof.output_dir=&lt;repertoire_pour_stocker_les_runs_xhprof&gt;
</pre>
<li><a name="using_extension"><h2>Profiler avec XHProf</h2></a>
<p>Test de génération de donées brutes avec lexemple simple dun programme tel que :
<ul>
<p><b>foo.php</b>
<pre>
&lt;?php
function bar($x) {
if ($x > 0) {
bar($x - 1);
}
}
function foo() {
for ($idx = 0; $idx < 2; $idx++) {
bar($idx);
$x = strlen("abc");
}
}
// début du profileur
<b>xhprof_enable();</b>
// début du programme
foo();
// attêt du profileur
<b>$xhprof_data = xhprof_disable();</b>
// affichage des données de profilage brutes
print_r($xhprof_data);
</pre>
</ul>
<p><b>Lancez ce programme :</b>
<pre>
% php -dextension=xhprof.so foo.php
</pre>
<p><b>Vous devez avoir un résultat tel que :</b>
<pre>
Array
(
[foo==>bar] => Array
(
[ct] => 2 # 2 appels de bar() depuis foo()
[wt] => 27 # temps inclusif dans bar() quand il est appelé par foo()
)
[foo==>strlen] => Array
(
[ct] => 2
[wt] => 2
)
[bar==>bar@1] => Array # un appelrécursif à bar()
(
[ct] => 1
[wt] => 2
)
[main()==>foo] => Array
(
[ct] => 1
[wt] => 74
)
[main()==>xhprof_disable] => Array
(
[ct] => 1
[wt] => 0
)
[main()] => Array # fausse fonction représentant la racine
(
[ct] => 1
[wt] => 83
)
)
</pre>
<p><b>Note:</b> Les données brutes contienent uniquement les métriques inclusives.
Par exemple les données brutes du tableau de données temporelles represente les temps inclusifs en microsecondes.
Les temps exclusifs sont calculés pour chaque fonction lors de la phase danalyse et de rapport.
<p><b>Note:</b> Par défault suelemnt le nombre dappel & et le temps passé sont profilés.
Vous pouvez aussi profilerle temps CPU et/ou la charge mémoire. Remplacez,
<ul><pre>
<b>xhprof_enable();</b>
</pre></ul>
dans le programme précédent avec, par exemple :
<ul><pre>
<b>xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY)</b>;
</pre></ul>
<p><b>Vous aurez en sortie :</b>
<pre>
Array
(
[foo==>bar] => Array
(
[ct] => 2 # nombre dappel à bar() depuis foo()
[wt] => 37 # tempas passé dans bar() quand appel de foo()
[cpu] => 0 # temps cpu time dans bar() quand appel de foo()
[mu] => 2208 # changement dans lusage de la mémoire par PHP dans bar() quand appel de foo()
[pmu] => 0 # changement dans lusage de pic mémoire par PHP pour bar() quand appel de foo()
)
[foo==>strlen] => Array
(
[ct] => 2
[wt] => 3
[cpu] => 0
[mu] => 624
[pmu] => 0
)
[bar==>bar@1] => Array
(
[ct] => 1
[wt] => 2
[cpu] => 0
[mu] => 856
[pmu] => 0
)
[main()==>foo] => Array
(
[ct] => 1
[wt] => 104
[cpu] => 0
[mu] => 4168
[pmu] => 0
)
[main()==>xhprof_disable] => Array
(
[ct] => 1
[wt] => 1
[cpu] => 0
[mu] => 344
[pmu] => 0
)
[main()] => Array
(
[ct] => 1
[wt] => 139
[cpu] => 0
[mu] => 5936
[pmu] => 0
)
)
</pre>
<p><b>Éviter les fonctions natives lors du profilage</b>
<p>Par défault les fonctions natives de PHP (comme <code>strlen</code>) sont profilées.
Si vous ne voulez pas les profiler (pour simplifier le résultat et la taille des données brutes générées),
Vous pouvez utiliser le drapeau <code><b>XHPROF_FLAGS_NO_BUILTINS</b></code> comme dans lexemple ci-dessous :
<ul><pre>
// ne pas profiler les fonctions natives
<b>xhprof_enable(XHPROF_FLAGS_NO_BUILTINS)</b>;
</pre></ul>
<p><b>Ignorer des fonctions spécfiques lors du profilage (0.9.2 ou plus récent)</b>
<p>À partir de la version 0.9.2 dXHProf, vous pouvez spécifier une liste de
fonctions à ignorer pendant le profilage. Cela vous permet de ne pas prendre en compte par exemple
des fonctions utilisées pour des appels indirects comme <code>call_user_func</code> et <code>call_user_func_array</code>.
Ces fonctions intermédiaires compliquent inutilement la hirarchie des appels et rendent plus ardue linterprétation des rapports en brouillant les relations parent/enfant.
<p>Pour spécifier cette liste de fonctions à ignorer durant le profilage, il suffit dutiliser le second paramètre (optionnel) de <code>xhprof_enable</code>.
Par exemple,
<pre>
<ul><pre>
<b>
// temps passé en profilage; ignore les appels de call_user_func* pendant le profilage
xhprof_enable(0,
array('ignored_functions' => array('call_user_func',
'call_user_func_array')));
</b>
or,
<b>
// tempas pasé en profilage + profilage mémoire; ignore call_user_func* durant le profilage
xhprof_enable(XHPROF_FLAGS_MEMORY,
array('ignored_functions' => array('call_user_func',
'call_user_func_array')));
</b>
</pre></ul>
</li>
<li><a name="ui_setup"><h2>Définir un environnement graphique pour XHProf</h2></a>
<ol>
<li><b>Structure de la source PHP</b>
<p>linterface graphique dXHProf est implémentée en PHP. Le code est divisé en deux sous-répertoires,
<code>xhprof_html/</code> and <code>xhprof_lib/</code>.
<p>Le répertoire <code>xhprof_html</code> contient les 3 pages PHP principales.
<ul>
<li><code>index.php</code>: Pour visualiser un run ou un différentiel entre deux runs.
<li><code>callgraph.php</code>: Pour visualiser sous la forme de graphique avec un rendu en image.
<li><code>typeahead.php</code>: Utilisé implicitement pour les fonctions de gestion de pile sur un rapport XHProf.
</ul>
<p>Le répertoire <code>xhprof_lib</code> contient le code pour lanalyse et laffichage.
(calcul sur les informations de profilage, calcul des différentiels, aggrégation de données, etc.).
<li><p><b>Configuration du server web : </b> Vous devez vous assurer que le répertoire
<code>xhprof_html/</code> est accessible depuis le serveur web, et quil est configuré pour éxécuter des scripts PHP.
<li><p><b>Gérer les runs XHProf</b>
<p>Les clients web ont une certaine souplesse dans la manière de sauvegarder les données brutes fournies par XHProf.
XHProf expose une interface utilisateur nommée iXHProfRuns (voir xhprof_lib/utils/xhprof_runs.php) que les clients peuvent implémenter.
Cela permet aux clients de préciser comment afficher les donées des runs.
<p>Linterface utilisateur dXHProf fournit une implementation par défaut nommée,
"XHProfRuns_Default" (aussi dans xhprof_lib/utils/xhprof_runs.php).
Limplementation par d"faut stocke les runs dans le répertoire définit par le paramètre INI :
<a href="#ini_file"><b>xhprof.output_dir</b></a>.
<p>Un run XHProf doit être définit de manière unique par un espace de nom et un identifiant de run.
<p><b>a) Sauver les données XHProf de façon persistente</b> :
<p>Soit si vous utilisez linterface par défaut,
<code><b>XHProfRuns_Default</b></code> qui implémente
<code><b>iXHProfRuns</b></code>, Un run XHProf sauvegardé ressemble au code suivant :
<pre>
// début du profilage
xhprof_enable();
// lancement du programme
...
// fin du profilage
$xhprof_data = xhprof_disable();
//
// Sauvegarde du run XHProf
// en utilisant limplementation par défaut de iXHProfRuns.
//
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";
$xhprof_runs = new <b>XHProfRuns_Default()</b>;
// sauvegarde du run avec lespace de nom "xhprof_foo".
//
// **NOTE**:
// par défault save_run() va automatiquement générer un identifiant de run
// unique. [Vous pouvez surcharger cette donnée en passant lidentifiant en paramètre optionnel
// à la méthode save_run().]
//
<b>$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");</b>
echo "---------------\n".
"En partant du principe que vous avez parametré linterface utilisateur http \n".
"XHProf, vous pouvez visualiser les runs avec ladresse : \n".
"http://&lt;adresse-interface-utilisateur-xhprof&gt;/index.php?run=$run_id&source=xhprof_foo\n".
"---------------\n";
</pre>
<p>La suite permet de sauvegarder le run sous forme dun fichier dans le répertoire spécifié
par le paramètre ini <code><b>xhprof.output_dir</b></code>. Le nom du fichier doit être de la forme
<b><code>49bafaa3a3f66.xhprof_foo</code></b>; Les deux parties du nom sont formées par lidentifiant du run
("49bafaa3a3f66") et lespace de nom ("xhprof_foo"). [Si vous souhaitez créer un identifiant de run vous-même
(comme une sequence de base de données, ou un timestamp), vous pouvez explicitementpasser lidentifiant
du run à la méthode <code>save_run</code>.
<p><b>b) En utilisant votre propre implementation diXHProfRuns</b>
<p> Si vous décidez de stocker différement les runs XHProf
(soit dans un format compressé, dans une base de données,
etc.), vous aurez besoin dimplémenter une classe qui implémente linterface
iXHProfRuns().
<p> Vous devrez également modifier les 3 pages PHP dentrée (index.php,
callgraph.php, typeahead.php) dans le répertoire "xhprof_html/" pour utiliser la
nouvelle interface au lieu de celle par défaut (<code>XHProfRuns_Default</code>),
changez cette ligne dans les 3 fichier.
<pre>
$xhprof_runs_impl = new XHProfRuns_Default();
</pre>
<p>Vous aurez aussi besoin dinclure le fichier qui implémente votre classe dans les fichiers cités.
<li><p><b>Acceéder aux runs depuis linterface utilisateur</b>
<p><b>a) Voir un rapport simple</b>
<p>Pour voir un rapport avec lidentifiant &lt;run_id&gt; et lespace de nom
&lt;namespace&gt; utilisez une url de la forme :
<p><code>
http://&lt;adresse-interface-utilisateur-xhprof&gt;/index.php?run=&lt;run_id&gt;&source=&lt;namespace&gt;
</code>
<p>Par example,
<p><code>
http://&lt;adresse-interface-utilisateur-xhprof&gt;/index.php?run=49bafaa3a3f66&source=xhprof_foo
</code>
<p><b>b) Voir un rapport différentiel</b>
<p>Pour voir un rapport avec les identifiants &lt;run_id1&gt; et
&lt;run_id2&gt; et lespace de nom &lt;namespace&gt; utilisez une url de la forme :
<p><code>
http://&lt;adresse-interface-utilisateur-xhprof&gt;/index.php?<b>run1=&lt;run_id1&gt;&run2=&lt;run_id2&gt;</b>&source=&lt;namespace&gt;
</code>
<p><b>c) Voir un rapport daggrégation</b>
<p>Vous pouvez aussi spécifier un ensemble de runspour lesquels vous souhaitez un rapport daggrégation.
<p>Si vous avez trois runs XHProf avec les identifiants 1, 2 & 3 pour lespace de noms
"benchmark". Pour voir laggrégation de ces trois runs :
<ul><p><code>
http://&lt;adresse-interface-utilisateur-xhprof&gt;/index.php?<b>run=1,2,3</b>&source=benchmark
</code></p></ul>
<p><b>Aggrégations pondérées</b>: En supposant que les trois runs
correspondent à trois types de programmes p1.php, p2.php and p3.php
qui occupent chacun respectivement 20%, 30% et 50%. Pour voir un rapport daggrégation
pondéré par les poids des runs :
<ul><p><code>
http://&lt;adresse-interface-utilisateur-xhprof&gt;/index.php?<b>run=1,2,3&wts=20,30,50</b>&source=benchmark
</code></p></ul>
</ol>
<li><a name="production_notes"><h2>Notes sur lutilisation dXHProf en production</h2></a>
<p>Quelques observations qui peuvent faire varier votre expérience :
<ul>
<li>Le timer CPU (getrusage) sur Linux peut avoir des dépassements de capacité. Il a également un rendu granuleux
(Une précision à la milliseconde plutôt quà la microseconde) pour être efficace au niveau des méthodes.
En conséquence, les valeurs rapportées en utilisant le mode XHPROF_FLAGS_CPU on tendance à être plus élevés.
<p>Nous recommandons dutiliser le mode de profilage "temps passé" + "memoire" en production.
[Note: Le surplus de temps passé par le mode de profilage mémoire est non significatif.]
<p><ul><pre><b>
// profilage du temps passé (par défault) + profilage mémoire
xhprof_enable(XHPROF_FLAGS_MEMORY);
</b></pre>
</ul></p>
<li>Profiler une plage aléatoire de pages/requêtes est efficace pour récupérer des données représentatives
de votre environnement de production.
<p>Pour profiler 1/10000 de vos requêtes, définissez le début du profilage avec un code dans lesprit de celui-ci :
<p><ul><pre><code>
if (mt_rand(1, 10000) == 1) {
xhprof_enable(XHPROF_FLAGS_MEMORY);
$xhprof_on = true;
}
</code></pre></ul></p>
<p>À la fin de la requête (ou dans une fonction de finalisation de la requête), vous pouvez faire quelque chose comme :
<p><ul><pre><code>
if ($xhprof_on) {
// fin du profilage
$xhprof_data = xhprof_disable();
// sauvegarde $xhprof_data quelquepart (base de données centralisée …)
...
}
</code></pre></ul></p>
<p> Vous pouvez alors récupérer et aggréger ces profilages par horaire
(par exemple 5 minutes, par jour, par jour …), par page ou type de requête, ou nimporte quel
paramètre utilisé par <a href="#xhprof_aggregate_runs"><code><b>xhprof_aggregate_runs()</b></code></a>.
</ul>
<li><a name="sampling_mode"><h2>Mode déchantillonage léger</h2></a>
<p>Lextension XHProf propose aussi un <b>mode très léger déchantillonage</b>.
Lintervalle est de 0,1 seconde. Les échantillons enregistrent lensemble des données.
Ce mode peut être très utile pour avoir un impact le plus négligeable possible, et permettre
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.
<p>Les très pertinentes fonctions utilisées par lextension pour utiliser le mode
déchantillonage sont <code><b>xhprof_sample_enable()</b></code> et <code><b>xhprof_sample_disable()</b></code>.
<p>[<b>TBD</b>: Documentation plus détaillée pour le mode déchantillonage.]
<li><a name="misc"><h2>Fonctionnalités supplémentaires</h2></a></li>
<p>Le fichier <code><b>XHProf_lib/utils/xhprof_lib.php</b></code> contient
des librairies de fonctions additionellesqui peuvent être utilisées pour manipuler
et aggréger les runs XHProf.
<p>Par exemple:
<ul>
<a name="xhprof_aggregate_runs"></a>
<p><li><code><b>xhprof_aggregate_runs()</b></code>:
peut être utilisé pour aggréger de multiples runs XHProf runs dans un seul run.
Cela peut être très utile pour fabriquer un outil de monitoring utilisant XHProf et à léchelle voulue.
[Par exemple, vous pouvez mixer des runs XHProf issus périodiquement
déchantillonage de la production pour générer des rapport journalier.]
<p><li><code><b>xhprof_prune_run()</b></code>: Aggréger une grande quantité de runs
(particulièrement si ils correspondent à des zones différentes du programme) peut créer un rendu
graphique beaucoup trop gros. Vous pouvez donc utiliser la fonction <code>xhprof_prune_run</code>
élaguer les données à afficher. En supprimant des branches qui compte pour une partie négligeable du temps passé.
</ul>
<ol>
</ol>
<li><a name="dependencies"><h2>Dependances</h2></a></li>
<ul>
<li><b>JQuery Javascript</b>: Pour les bulles daides et les noms de fonctions de pile,
nous utilisons la librairie Javascript, JQuery. JQuery est disponible sous les licences MIT et GPL
(http://docs.jquery.com/Licensing). Ce code JQuery, utilisé par XHProf, se trouve dans le
sous répertoire <code>xhprof_html/jquery</code>.
<li><b>dot (utilitaire de génération dimage):</b> Le fonctionnalité de rendu graphique
([View Callgraph]) est présente grâce à la présence de Graphviz "dot" dans votre path.
"dot" est un utilitaire de dessin et de gén"ration dimage.
</ul>
<li><a name="credits"><h2>Remerciements</h2></a>
<p>Le rendu HTML et linterface de navigation pour consulter les résultat du profilage sont inspirés par un outil similaire
qui existe pour les procédures stockées PL/SQL dOracle. Mais cest là que la comparaison sarrête;
Le fonctionnement interne du profileur étant assez différent
[NDT : Merci à Rudy Rigot (@rudyrigot) pour sa relecture attentive ]
</li>
</ol>
</body>
</html>

View file

@ -0,0 +1,826 @@
<html>
<title>
XHProf Documentation (Draft)
</title>
<body>
<h3>XHProf Documentation (Draft)</h3>
<b>Contents</b>
<ol>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#overview">XHProf Overview</a></li>
<li><a href="#installation">Installing the XHProf extension</a></li>
<li><a href="#using_extension">Profiling using XHProf</a></li>
<li><a href="#ui_setup">Setting up the XHProf UI</a></li>
<li><a href="#production_notes">Notes on using XHProf in production</a></li>
<li><a href="#sampling_mode">Lightweight Sampling Mode</a>
<li><a href="#misc">Additional features</a></li>
<li><a href="#dependencies">Dependencies</a></li>
<li><a href="#credits">Acknowledgements</a></li>
</ol>
<ol>
<li><a name="introduction"><h2>Introduction</h2></a>
<p>XHProf is a hierarchical profiler for PHP. It reports
function-level call counts and <a href="#inclusive">inclusive</a> and
<a href="#exclusive">exclusive</a> metrics such as wall (elapsed)
time, CPU time and memory usage. A function's profile can be broken
down by callers or callees. The raw data collection component is
implemented in C as a PHP Zend extension called
<code><b>xhprof</b></code>. XHProf has a simple HTML based user
interface (written in PHP). The browser based UI for viewing profiler
results makes it easy to view results or to share results with peers.
A callgraph image view is also supported.
<p>XHProf reports can often be helpful in understanding the structure
of the code being executed. The hierarchical nature of the reports can
be used to determine, for example, what chain of calls led to a
particular function getting called.
<p>XHProf supports ability to compare two runs (a.k.a. "diff" reports)
or aggregate data from multiple runs. Diff and aggregate reports, much
like single run reports, offer "flat" as well as "hierarchical" views
of the profile.
<p>XHProf is a light-weight instrumentation based profiler. During the
data collection phase, it keeps track of call counts and inclusive
metrics for arcs in the dynamic callgraph of a program. It computes
exclusive metrics in the reporting/post processing phase. XHProf
handles recursive functions by detecting cycles in the callgraph at
data collection time itself and avoiding the cycles by giving unique
depth qualified names for the recursive invocations.
</p>
<p>XHProf's light-weight nature and aggregation capabilities make it
well suited for collecting "function-level" performance statistics
from production environments. [See <a
href="#production_notes">additional notes</a> for use in production.]
<ul>
<hr>
<p>XHProfLive (not part of the open source kit), for example, is a
system-wide performance monitoring system in use at Facebook that is
built on top of XHProf. XHProfLive continually gathers function-level
profiler data from production tier by running a sample of page
requests under XHProf. XHProfLive then aggregates the profile data
corresponding to individual requests by various dimensions such as
time, page type, and can help answer a variety of questions such as:
What is the function-level profile for a specific page? How expensive
is function "foo" across all pages, or on a specific page? What
functions regressed most in the last hour/day/week? What is the
historical trend for execution time of a page/function? and so on.
<hr>
</ul>
<p>Originally developed at Facebook, XHProf was open sourced in Mar, 2009.</p>
</ul>
<li><a name="overview"><h2>XHProf Overview</h2></a>
<p>XHProf provides:
<ul>
<li><b>Flat profile</b> (<a href="sample-flat-view.jpg" >screenshot</a>)
<p>Function-level summary information such as number of calls,
inclusive/exclusive wall time, memory usage, and CPU time.
<p><li><b>Hierarchical profile (Parent/Child View)</b>
(<a href="sample-parent-child-view.jpg" >screenshot</a>)
<p>For each function, it provides a breakdown of calls and times per
parent (caller) & child (callee), such as:
<ul>
<li> what functions call a particular function and how many times?
<li> what functions does a particular function call?
<li> The total time spent under a function when called from a particular parent.
</ul>
<p><li><b>Diff Reports</b>
<p>You may want to compare data from two XHProf runs for various
reasons-- to figure out what's causing a regression between one
version of the code base to another, to evaluate the performance
improvement of a code change you are making, and so on.
<p>A diff report takes two runs as input and provides both flat
function-level diff information, and hierarchical information
(breakdown of diff by parent/children functions) for each function.
<p>The "flat" view (<a href="sample-diff-report-flat-view.jpg"
>sample screenshot</a>) in the diff report points out the top
regressions & improvements.
<p>Clicking on functions in the "flat" view of the diff report, leads
to the "hierarchical" (or parent/child) diff view of a function (<a href="sample-diff-report-parent-child-view.jpg"
>sample screenshot</a>). We can get a
breakdown of the diff by parent/children functions.
<p><li><b>Callgraph View</b> (<a href="sample-callgraph-image.jpg"
>sample screenshot</a>)
<p>The profile data can also be viewed as a callgraph. The callgraph
view highlights the critical path of the program.
<p><li><b>Memory Profile</b>
<p>XHProf's memory profile mode helps track functions that
allocate lots of memory.
<p>It is worth clarifying that that XHProf doesn't strictly track each
allocation/free operation. Rather it uses a more simplistic
scheme. It tracks the increase/decrease in the amount of memory
allocated to PHP between each function's entry and exit. It also
tracks increase/decrease in the amount of <b>peak</b> memory allocated to
PHP for each function.
<li>XHProf tracks <code>include, include_once, require and
require_once</code> operations as if they were functions. The name of
the file being included is used to generate the name for these <a
href="#include_funcs">"fake" functions</a>.
</ul>
<a name="Terminology"></a><h2>Terminology</h2>
<ol>
<a name="inclusive"></a><li><b>Inclusive Time (or Subtree Time)</b>:
Includes time spent in the function as well as in descendant functions
called from a given function.
<a name="exclusive"></a><li><b>Exclusive Time/Self Time</b>: Measures
time spent in the function itself. Does not include time in descendant
functions.
<li><b>Wall Time</b>: a.k.a. Elapsed time or wall clock time.
<li><b>CPU Time</b>: CPU time in user space + CPU time in kernel space
</ol>
<a name="Naming_convention_for_special_functions"></a><h2>Naming convention for special functions</h2>
<ol>
<p><li><code><b>main()</b></code>: a fictitious function that is at the root of the call graph.
<a name="include_funcs"></a>
<p><li><code><b>load::&lt;filename&gt;</b></code>
and <code><b>run_init::&lt;filename&gt;</b></code>:
<p>XHProf tracks PHP <code>include/require</code> operations as
function calls.
<p>For example, an <b>include "lib/common.php";</b> operation will
result in two XHProf function entries:
<ul>
<li> <code><b>load::lib/common.php</b></code> - This represents the work done by the
interpreter to compile/load the file. [Note: If you are using a PHP
opcode cache like APC, then the compile only happens on a cache miss
in APC.]
<li> <code><b>run_init::lib/common.php</b></code> - This represents
initialization code executed at the file scope as a result of the
include operation.
</ul>
<p><li><code><b>foo@&lt;n&gt;</b></code>: Implies that this is a
recursive invocation of <code>foo()</code>, where <code>&lt;n&gt;</code> represents
the recursion depth. The recursion may be direct (such as due to
<code>foo()</code> --&gt; <code>foo()</code>), or indirect (such as
due to </code>foo()</code> --&gt; <code>goo()</code> --&gt; foo()).
</ol>
<a name="Limitations"></a><h2>Limitations</h2>
<p>True hierarchical profilers keep track of a full call stack at
every data gathering point, and are later able to answer questions
like: what was the cost of the 3rd invokation of foo()? or what was
the cost of bar() when the call stack looked like
a()-&gt;b()-&gt;bar()?
</p>
<p>XHProf keeps track of only 1-level of calling context and is
therefore only able to answer questions about a function looking
either 1-level up or 1-level down. It turns out that in practice this
is sufficient for most use cases.
</p>
<p>To make this more concrete, take for instance the following
example.
</p>
<pre>
Say you have:
1 call from a() --&gt; c()
1 call from b() --&gt; c()
50 calls from c() --&gt; d()
</pre>
<p>While XHProf can tell you that d() was called from c() 50 times, it
cannot tell you how many of those calls were triggered due to a()
vs. b(). [We could speculate that perhaps 25 were due to a() and 25
due to b(), but that's not necessarily true.]
</p>
<p>In practice however, this isn't a very big limitation.
</p>
<li><a name="installation"><h2>Installing the XHProf Extension</h2></a>
<p> The extension lives in the "extension/" sub-directory.
<ul><hr>
<p><b>Note:</b> A windows port hasn't been implemented yet. We have
tested <code>xhprof</code> on <b>Linux/FreeBSD</b> so far.
<p>Version 0.9.2 and above of XHProf is also expected to work on <b>Mac
OS</b>. [We have tested on Mac OS 10.5.]
<p><b>Note:</b> XHProf uses the RDTSC instruction (time stamp counter)
to implement a really low overhead timer for elapsed time. So at the
moment <code>xhprof</code> only works on <b>x86</b> architecture.
Also, since RDTSC values may not be synchronized across CPUs,
<code>xhprof</code> binds the program to a single CPU during the
profiling period.
<p>XHProf's RDTSC based timer functionality doesn't work correctly if
<b>SpeedStep</b> technology is turned on. This technology is available on
some Intel processors. [Note: Mac desktops and laptops typically have
SpeedStep turned on by default. To use XHProf, you'll need to disable
SpeedStep.]
<hr></ul>
<p> The steps
below should work for Linux/Unix environments.
<pre>
% cd &lt;xhprof_source_directory&gt;/extension/
% phpize
% ./configure --with-php-config=&lt;path to php-config&gt;
% make
% make install
% make test
</pre>
<p><a name="ini_file"></a><b>php.ini file</b>: You can update your
php.ini file to automatically load your extension. Add the following
to your php.ini file.
<pre>
[xhprof]
extension=xhprof.so
;
; directory used by default implementation of the iXHProfRuns
; interface (namely, the XHProfRuns_Default class) for storing
; XHProf runs.
;
xhprof.output_dir=&lt;directory_for_storing_xhprof_runs&gt;
</pre>
<li><a name="using_extension"><h2>Profiling using XHProf</h2></a>
<p>Test generating raw profiler data using a sample test program like:
<ul>
<p><b>foo.php</b>
<pre>
&lt;?php
function bar($x) {
if ($x > 0) {
bar($x - 1);
}
}
function foo() {
for ($idx = 0; $idx < 2; $idx++) {
bar($idx);
$x = strlen("abc");
}
}
// start profiling
<b>xhprof_enable();</b>
// run program
foo();
// stop profiler
<b>$xhprof_data = xhprof_disable();</b>
// display raw xhprof data for the profiler run
print_r($xhprof_data);
</pre>
</ul>
<p><b>Run the above test program:</b>
<pre>
% php -dextension=xhprof.so foo.php
</pre>
<p><b>You should get an output like:</b>
<pre>
Array
(
[foo==>bar] => Array
(
[ct] => 2 # 2 calls to bar() from foo()
[wt] => 27 # inclusive time in bar() when called from foo()
)
[foo==>strlen] => Array
(
[ct] => 2
[wt] => 2
)
[bar==>bar@1] => Array # a recursive call to bar()
(
[ct] => 1
[wt] => 2
)
[main()==>foo] => Array
(
[ct] => 1
[wt] => 74
)
[main()==>xhprof_disable] => Array
(
[ct] => 1
[wt] => 0
)
[main()] => Array # fake symbol representing root
(
[ct] => 1
[wt] => 83
)
)
</pre>
<p><b>Note:</b> The raw data only contains "inclusive" metrics. For
example, the wall time metric in the raw data represents inclusive
time in microsecs. Exclusive times for any function are computed
during the analysis/reporting phase.
<p><b>Note:</b> By default only call counts & elapsed time is profiled.
You can optionally also profile CPU time and/or memory usage. Replace,
<ul><pre>
<b>xhprof_enable();</b>
</pre></ul>
in the above program with, for example:
<ul><pre>
<b>xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY)</b>;
</pre></ul>
<p><b>You should now get an output like:</b>
<pre>
Array
(
[foo==>bar] => Array
(
[ct] => 2 # number of calls to bar() from foo()
[wt] => 37 # time in bar() when called from foo()
[cpu] => 0 # cpu time in bar() when called from foo()
[mu] => 2208 # change in PHP memory usage in bar() when called from foo()
[pmu] => 0 # change in PHP peak memory usage in bar() when called from foo()
)
[foo==>strlen] => Array
(
[ct] => 2
[wt] => 3
[cpu] => 0
[mu] => 624
[pmu] => 0
)
[bar==>bar@1] => Array
(
[ct] => 1
[wt] => 2
[cpu] => 0
[mu] => 856
[pmu] => 0
)
[main()==>foo] => Array
(
[ct] => 1
[wt] => 104
[cpu] => 0
[mu] => 4168
[pmu] => 0
)
[main()==>xhprof_disable] => Array
(
[ct] => 1
[wt] => 1
[cpu] => 0
[mu] => 344
[pmu] => 0
)
[main()] => Array
(
[ct] => 1
[wt] => 139
[cpu] => 0
[mu] => 5936
[pmu] => 0
)
)
</pre>
<p><b>Skipping builtin functions during profiling</b>
<p>By default PHP builtin functions (such as <code>strlen</code>) are
profiled. If you do not want to profile builtin functions (to either
reduce the overhead of profiling further or size of generated raw
data), you can use the <code><b>XHPROF_FLAGS_NO_BUILTINS</b></code>
flag as in for example:
<ul><pre>
// do not profile builtin functions
<b>xhprof_enable(XHPROF_FLAGS_NO_BUILTINS)</b>;
</pre></ul>
<p><b>Ignoring specific functions during profiling (0.9.2 or higher)</b>
<p>Starting with release 0.9.2 of xhprof, you can tell XHProf to
ignore a specified list of functions during profiling. This allows you
to ignore, for example, functions used for indirect function calls
such as <code>call_user_func</code> and
<code>call_user_func_array</code>. These intermediate functions
unnecessarily complicate the call hierarchy and make the XHProf
reports harder to interpret since they muddle the parent-child
relationship for functions called indirectly.
<p> To specify the list of functions to be ignored during profiling
use the 2nd (optional) argument to <code>xhprof_enable</code>.
For example,
<pre>
<ul><pre>
<b>
// elapsed time profiling; ignore call_user_func* during profiling
xhprof_enable(0,
array('ignored_functions' => array('call_user_func',
'call_user_func_array')));
</b>
or,
<b>
// elapsed time + memory profiling; ignore call_user_func* during profiling
xhprof_enable(XHPROF_FLAGS_MEMORY,
array('ignored_functions' => array('call_user_func',
'call_user_func_array')));
</b>
</pre></ul>
</li>
<li><a name="ui_setup"><h2>Setting up XHProf UI</h2></a>
<ol>
<li><b>PHP source structure</b>
<p>The XHProf UI is implemented in PHP. The code resides in two
subdirectories, <code>xhprof_html/</code> and <code>xhprof_lib/</code>.
<p>The <code>xhprof_html</code> directory contains the 3 top-level PHP pages.
<ul>
<li><code>index.php</code>: For viewing a single run or diff report.
<li><code>callgraph.php</code>: For viewing a callgraph of a XHProf run as an image.
<li><code>typeahead.php</code>: Used implicitly for the function typeahead form
on a XHProf report.
</ul>
<p>The <code>xhprof_lib</code> directory contains supporting code for
display as well as analysis (computing flat profile info, computing
diffs, aggregating data from multiple runs, etc.).
<li><p><b>Web server config: </b> You'll need to make sure that the
<code>xhprof_html/</code> directory is accessible from your web server, and that
your web server is setup to serve PHP scripts.
<li><p><b>Managing XHProf Runs</b>
<p>Clients have flexibility in how they save the XHProf raw data
obtained from an XHProf run. The XHProf UI layer exposes an interface
iXHProfRuns (see xhprof_lib/utils/xhprof_runs.php) that clients can
implement. This allows the clients to tell the UI layer how to fetch
the data corresponding to a XHProf run.
<p>The XHProf UI libaries come with a default file based
implementation of the iXHProfRuns interface, namely
"XHProfRuns_Default" (also in xhprof_lib/utils/xhprof_runs.php).
This default implementation stores runs in the directory specified by
<a href="#ini_file"><b>xhprof.output_dir</b></a> INI parameter.
<p>A XHProf run must be uniquely identified by a namespace and a run
id.
<p><b>a) Saving XHProf data persistently</b>:
<p>Assuming you are using the default implementation
<code><b>XHProfRuns_Default</b></code> of the
<code><b>iXHProfRuns</b></code> interface, a typical XHProf run
followed by the save step might look something like:
<pre>
// start profiling
xhprof_enable();
// run program
....
// stop profiler
$xhprof_data = xhprof_disable();
//
// Saving the XHProf run
// using the default implementation of iXHProfRuns.
//
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";
$xhprof_runs = new <b>XHProfRuns_Default()</b>;
// Save the run under a namespace "xhprof_foo".
//
// **NOTE**:
// By default save_run() will automatically generate a unique
// run id for you. [You can override that behavior by passing
// a run id (optional arg) to the save_run() method instead.]
//
<b>$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");</b>
echo "---------------\n".
"Assuming you have set up the http based UI for \n".
"XHProf at some address, you can view run at \n".
"http://&lt;xhprof-ui-address&gt;/index.php?run=$run_id&source=xhprof_foo\n".
"---------------\n";
</pre>
<p>The above should save the run as a file in the directory specified
by the <code><b>xhprof.output_dir</b></code> INI parameter. The file's
name might be something like
<b><code>49bafaa3a3f66.xhprof_foo</code></b>; the two parts being the
run id ("49bafaa3a3f66") and the namespace ("xhprof_foo"). [If you
want to create/assign run ids yourself (such as a database sequence
number, or a timestamp), you can explicitly pass in the run id to the
<code>save_run</code> method.
<p><b>b) Using your own implementation of iXHProfRuns</b>
<p> If you decide you want your XHProf runs to be stored differently
(either in a compressed format, in an alternate place such as DB,
etc.) database, you'll need to implement a class that implements the
iXHProfRuns() interface.
<p> You'll also need to modify the 3 main PHP entry pages (index.php,
callgraph.php, typeahead.php) in the "xhprof_html/" directory to use
the new class instead of the default class <code>XHProfRuns_Default</code>.
Change this line in the 3 files.
<pre>
$xhprof_runs_impl = new XHProfRuns_Default();
</pre>
<p>You'll also need to "include" the file that implements your class in
the above files.
<li><p><b>Accessing runs from UI</b>
<p><b>a) Viewing a Single Run Report</b>
<p>To view the report for run id say &lt;run_id&gt; and namespace
&lt;namespace&gt; use a URL of the form:
<p><code>
http://&lt;xhprof-ui-address&gt;/index.php?run=&lt;run_id&gt;&source=&lt;namespace&gt;
</code>
<p>For example,
<p><code>
http://&lt;xhprof-ui-address&gt;/index.php?run=49bafaa3a3f66&source=xhprof_foo
</code>
<p><b>b) Viewing a Diff Report</b>
<p>To view the report for run ids say &lt;run_id1&gt; and
&lt;run_id2&gt; in namespace &lt;namespace&gt; use a URL of the form:
<p><code>
http://&lt;xhprof-ui-address&gt;/index.php?<b>run1=&lt;run_id1&gt;&run2=&lt;run_id2&gt;</b>&source=&lt;namespace&gt;
</code>
<p><b>c) Aggregate Report</b>
<p>You can also specify a set of run ids for which you want an aggregated view/report.
<p>Say you have three XHProf runs with ids 1, 2 & 3 in namespace
"benchmark". To view an aggregate report of these runs:
<ul><p><code>
http://&lt;xhprof-ui-address&gt;/index.php?<b>run=1,2,3</b>&source=benchmark
</code></p></ul>
<p><b>Weighted aggregations</b>: Further suppose that the above three runs
correspond to three types of programs p1.php, p2.php and p3.php that
typically occur in a mix of 20%, 30%, 50% respectively. To view an
aggregate report that corresponds to a weighted average of these runs
using:
<ul><p><code>
http://&lt;xhprof-ui-address&gt;/index.php?<b>run=1,2,3&wts=20,30,50</b>&source=benchmark
</code></p></ul>
</ol>
<li><a name="production_notes"><h2>Notes on using XHProf in production</h2></a>
<p>Some observations/guidelines. Your mileage may vary:
<ul>
<li>CPU timer (getrusage) on Linux has high overheads. It is also
coarse grained (millisec accuracy rather than microsec level) to be
useful at function level. Therefore, the skew in reported numbers
when using XHPROF_FLAGS_CPU mode tends to be higher.
<p>We recommend using elapsed time + memory profiling mode in
production. [Note: The additional overhead of memory profiling
mode is really low.]
<p><ul><pre><b>
// elapsed time profiling (default) + memory profiling
xhprof_enable(XHPROF_FLAGS_MEMORY);
</b></pre>
</ul></p>
<li>Profiling a random sample of pages/requests works well in capturing
data that is representative of your production workload.
<p>To profile say 1/10000 of your requests, instrument the beginning of
your request processing with something along the lines of:
<p><ul><pre><code>
if (mt_rand(1, 10000) == 1) {
xhprof_enable(XHPROF_FLAGS_MEMORY);
$xhprof_on = true;
}
</code></pre></ul></p>
<p>At the end of the request (or in a request shutdown function), you might
then do something like:
<p><ul><pre><code>
if ($xhprof_on) {
// stop profiler
$xhprof_data = xhprof_disable();
// save $xhprof_data somewhere (say a central DB)
...
}
</code></pre></ul></p>
<p> You can then rollup/aggregate these individual profiles by time
(e.g., 5 minutely/hourly/daily basis), page/request type,or other
dimensions using <a href="#xhprof_aggregate_runs"><code><b>xhprof_aggregate_runs()</b></code></a>.
</ul>
<li><a name="sampling_mode"><h2>Lightweight Sampling Mode</h2></a>
<p>The xhprof extension also provides a very light weight <b>sampling
mode</b>. The sampling interval is 0.1 secs. Samples record the full
function call stack. The sampling mode can be useful if an extremely
low overhead means of doing performance monitoring and diagnostics is
desired.
<p> The relevant functions exposed by the extension for using the
sampling mode are <code><b>xhprof_sample_enable()</b></code> and
<code><b>xhprof_sample_disable()</b></code>.
<p>[<b>TBD</b>: more detailed documentation on sampling mode.]
<li><a name="misc"><h2>Additional Features</h2></a></li>
<p>The <code><b>xhprof_lib/utils/xhprof_lib.php</b></code> file contains
additional library functions that can be used for manipulating/
aggregating XHProf runs.
<p>For example:
<ul>
<a name="xhprof_aggregate_runs"></a>
<p><li><code><b>xhprof_aggregate_runs()</b></code>:
can be used to aggregate multiple XHProf runs into a single run. This
can be helpful for building a system-wide "function-level" performance
monitoring tool using XHProf. [For example, you might to roll up
XHProf runs sampled from production periodically to generate hourly,
daily, reports.]
<p><li><code><b>xhprof_prune_run()</b></code>: Aggregating large number of
XHProf runs (especially if they correspond to different types of
programs) can result in the callgraph size becoming too large. You can
use <code>xhprof_prune_run</code> function to prune the callgraph data
by editing out subtrees that account for a very small portion of the
total time.
</ul>
<ol>
</ol>
<li><a name="dependencies"><h2>Dependencies</h2></a></li>
<ul>
<li><b>JQuery Javascript</b>: For tooltips and function name
typeahead, we make use of JQuery's javascript libraries. JQuery is
available under both a MIT and GPL licencse
(http://docs.jquery.com/Licensing). The relevant JQuery code, used by
XHProf, is in the <code>xhprof_html/jquery</code> subdirectory.
<li><b>dot (image generation utility):</b> The callgraph image
visualization ([View Callgraph]) feature relies on the presence of
Graphviz "dot" utility in your path. "dot" is a utility to
draw/generate an image for a directed graph.
</ul>
<li><a name="credits"><h2>Acknowledgements</h2></a>
<p>The HTML-based navigational interface for browsing profiler results
is inspired by that of a similar tool that exists for Oracle's stored
procedure language, PL/SQL. But that's where the similarity ends; the
internals of the profiler itself are quite different.
</li>
</ol>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View file

@ -31,15 +31,6 @@
// Changhao Jiang // Changhao Jiang
// //
// Start moodle modification: moodleize this script.
require_once(dirname(dirname(dirname(dirname(__FILE__)))).'/config.php');
require_once($CFG->libdir . '/xhprof/xhprof_moodle.php');
require_login();
require_capability('moodle/site:config', context_system::instance());
raise_memory_limit(MEMORY_HUGE);
\core\session\manager::write_close();
// End moodle modification.
// by default assume that xhprof_html & xhprof_lib directories // by default assume that xhprof_html & xhprof_lib directories
// are at the same level. // are at the same level.
$GLOBALS['XHPROF_LIB_ROOT'] = dirname(__FILE__) . '/../xhprof_lib'; $GLOBALS['XHPROF_LIB_ROOT'] = dirname(__FILE__) . '/../xhprof_lib';
@ -89,10 +80,7 @@ $vbbar = ' class="vbbar"';
$vrbar = ' class="vrbar"'; $vrbar = ' class="vrbar"';
$vgbar = ' class="vgbar"'; $vgbar = ' class="vgbar"';
// Start moodle modification: use own XHProfRuns implementation. $xhprof_runs_impl = new XHProfRuns_Default();
// $xhprof_runs_impl = new XHProfRuns_Default();
$xhprof_runs_impl = new moodle_xhprofrun();
// End moodle modification.
displayXHProfReport($xhprof_runs_impl, $params, $source, $run, $wts, displayXHProfReport($xhprof_runs_impl, $params, $source, $run, $wts,
$symbol, $sort, $run1, $run2); $symbol, $sort, $run1, $run2);

View file

@ -21,22 +21,12 @@
* Changhao Jiang * Changhao Jiang
*/ */
// Start moodle modification: moodleize this script.
require_once(dirname(dirname(dirname(dirname(__FILE__)))).'/config.php');
require_once($CFG->libdir . '/xhprof/xhprof_moodle.php');
require_login();
require_capability('moodle/site:config', context_system::instance());
\core\session\manager::write_close();
// End moodle modification.
// by default assume that xhprof_html & xhprof_lib directories // by default assume that xhprof_html & xhprof_lib directories
// are at the same level. // are at the same level.
$GLOBALS['XHPROF_LIB_ROOT'] = dirname(__FILE__) . '/../xhprof_lib'; $GLOBALS['XHPROF_LIB_ROOT'] = dirname(__FILE__) . '/../xhprof_lib';
require_once $GLOBALS['XHPROF_LIB_ROOT'].'/display/xhprof.php'; require_once $GLOBALS['XHPROF_LIB_ROOT'].'/display/xhprof.php';
// Start moodle modification: use own XHProfRuns implementation. $xhprof_runs_impl = new XHProfRuns_Default();
$xhprof_runs_impl = new moodle_xhprofrun();
// End moodle modification.
require_once $GLOBALS['XHPROF_LIB_ROOT'].'/display/typeahead_common.php'; require_once $GLOBALS['XHPROF_LIB_ROOT'].'/display/typeahead_common.php';

View file

@ -107,11 +107,7 @@ function xhprof_generate_image_by_dot($dot_script, $type) {
2 => array("pipe", "w") 2 => array("pipe", "w")
); );
// Start moodle modification: use $CFG->pathtodot for executing this. $cmd = " dot -T".$type;
// $cmd = " dot -T".$type;
global $CFG;
$cmd = (!empty($CFG->pathtodot) ? $CFG->pathtodot : 'dot') . ' -T' . $type;
// End moodle modification.
$process = proc_open( $cmd, $descriptorspec, $pipes, sys_get_temp_dir(), array( 'PATH' => getenv( 'PATH' ) ) ); $process = proc_open( $cmd, $descriptorspec, $pipes, sys_get_temp_dir(), array( 'PATH' => getenv( 'PATH' ) ) );
if (is_resource($process)) { if (is_resource($process)) {