Optimisez vos scripts PHP avec le profiler XDebug


Technique

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 :

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 :

Laisser un commentaire