XDebug est une extension PHP améliorant grandement la phase de développement et d'optimisation d'une application web, en apportant des fonctionnalités avancées de débogage et de profiling.
Nous nous intéresserons ici au profiler.
Installation
Sur une Debian :
Il vous faut avant tout installer PEAR, ainsi que le paquet php5-dev :
sudo apt-get install php5-dev
sudo apt-get install php-pear
Puis installer l'extension XDebug grâce à PEAR :
sudo pecl install xdebug
Sur Windows :
Il suffit de vous rendre sur le site officiel XDebug, et de sélectionner le fichier DLL correspondant à la version de votre PHP.
Déplacez ensuite ce fichier dans votre répertoire d'extensions de PHP (n'hésitez pas à jeter un coup d'oeil sur la documentation officielle si besoin).
Sur Mac :
Vous devez récupérer les sources de XDebug, et les compiler manuellement :
git clone https://github.com/derickr/xdebug.git
cd xdebug
phpize
./configure --enable-xdebug
Copiez ensuite le répertoire modules fraichement créé, dans votre répertoire d'extensions de PHP :
cp -r modules/ /usr/local/xdebug
Activation et configuration
Il vous faut dorénavant activer l'extension. Pour cela, il suffit d'ajouter dans votre fichier php.ini :
Sur Debian ou Mac :
zend_extension=/chemin/vers/fichier/xdebug.so
Sur Windows :
zend_extension=C:\chemin\vers\fichier\xdebug.so
Ensuite la configuration basique du profiler XDebug est la suivante (à mettre dans le fichier php.ini) :
# Activation du Profiler
xdebug.profiler_enable=1
# Répertoire de destination des fichiers de profiling
xdebug.profiler_output_dir="/tmp/"
# Format du nom des fichiers de profiling
xdebug.profiler_output_name="cachegrind.%s.out"
Pensez à redémarrer votre serveur PHP, et vous êtes prêts à vous lancer dans l'optimisation de votre application !
Analyse des fichiers de profiling
Dorénavant, à chaque fois que vous executez un script PHP, un fichier de profiling est généré. Ce dernier contient toutes les informations nécessaires à l'analyse détaillée de votre code.
Logiciels de profiling
Pour lire ce fichier, il existe plusieurs logiciels, les principaux étant :
KCacheGrind pour Linux
WinCacheGrind pour Windows
QCacheGrind pour Mac
Les exemples suivants seront traités avec KCacheGrind, mais le fonctionnement reste similaire pour WinCacheGrind et QCacheGrind.
Exemple
<!--?php
class Test
{
private $_oPDO;
public function __construct($oPDO)
{
$this->_oPDO = $oPDO;
}
function getUserInfos($iUserId)
{
$sSql = 'SELECT id, name, id_job FROM user';
foreach ($this->_oPDO->query($sSql) as $aRow) {
$sJobName = $this->getJobName($aRow['id_job']);
if ($aRow['id'] == $iUserId) {
return array(
'name' => $aRow['name'],
'job' => $sJobName,
);
}
}
return null;
}
function getJob($iJobId)
{
$sSql = 'SELECT id, name FROM job';
foreach ($this->_oPDO->query($sSql) as $aRow) {
if ($aRow['id'] == $iUserId) {
return $aRow['name'];
}
}
return null;
}
}
$oTest = new Test($oPDO);
var_dump($oTest->getUserInfos(16));
Ce code est très simple, il se charge simplement de récupérer les informations (nom et travail) d'un utilisateur à partir de son identifiant.
Une fois executé, le fichier de profling est généré. Ouvrons-le avec KCacheGrind :
article blog.20140630 1 1024x711 Optimisez vos scripts PHP avec le profiler XDebug
La partie qui nous intéresse ici, c'est le graphique à droite, dans lequel on peut lire que :
La méthode Test->getUserInfos a été appelée une fois.
Cette méthode a à son tour appelé 2143 fois la méthode Test->getJobName.
On constate ici une anomalie au niveau du nombre d'appels de la méthode Test->getJobName.
En regardant de plus près le code source, plus précisément la méthode getUserInfos, on s'aperçoit que pour chaque utilisateur, le nom de son métier est récupéré. Il est donc très simple d'optimiser cette partie en limitant le nombre d'appels à la méthode getJobName effectués.
Il suffit de ne récupérer que le nom du métier de l'utilisateur recherché :
function getUserInfos($iUserId)
{
$sSql = 'SELECT id, name, id_job FROM user';
foreach ($this->_oPDO->query($sSql) as $aRow) {
if ($aRow['id'] == $iUserId) {
$sJobName = $this->getJobName($aRow['id_job']);
return array(
'name' => $aRow['name'],
'job' => $sJobName,
);
}
}
return null;
}
Voici le nouveau profiling une fois la modification effectuée :
article blog.20140630 2 1024x711 Optimisez vos scripts PHP avec le profiler XDebug
Et voilà, nous sommes passés de 2143 appels, à seulement un ! Certes cet exemple n'est pas très réaliste, et loin d'être optimum pour bien d'autres raisons, mais il permet de mettre en évidence l'importance du profiling de son code, et surtout l'incroyable gain de performance que vous pouvez obtenir en corrigeant de simples choses dans votre application.
Pour aller plus loin
XDebug est un outil très puissant, nous n'avons vu qu'une petite partie de ce que nous offre le profiler. Si vous souhaitez appronfondir le sujet, nous vous invitons à visiter les sites suivants :
La documentation officielle du profiler XDebug (en anglais)
Un tutorial complet sur XDebug, par Julien Pauli
Configurer XDebug sur PHPStorm (en anglais)