web-dev-qa-db-fra.com

Comment puis-je mesurer la vitesse du code écrit en PHP?

Comment puis-je dire quelle classe de la classe (qui font toutes le même travail) s'exécute plus rapidement? Existe-t-il un logiciel pour mesurer cela?

109
M. A. Kishawy

Vous avez (au moins) deux solutions:

Celui qui est assez "naïf" utilise microtime (true) avant et après une partie du code pour obtenir le temps écoulé depuis son exécution; d’autres réponses ont dit cela et ont déjà donné des exemples, donc je ne vais pas en dire beaucoup plus.

C'est une bonne solution si vous souhaitez comparer quelques instructions. comme comparer deux types de fonctions, par exemple - il est préférable de le faire des milliers de fois, pour s'assurer que tout "élément perturbateur" est moyenné.

Quelque chose comme ça, donc, si vous voulez savoir combien de temps il faut pour sérialiser un tableau:

$before = microtime(true);

for ($i=0 ; $i<100000 ; $i++) {
    serialize($list);
}

$after = microtime(true);
echo ($after-$before)/$i . " sec/serialize\n";

Pas parfait, mais utile, et sa mise en place ne prend pas beaucoup de temps.



L'autre solution, qui fonctionne assez bien si vous voulez identifier quelle fonction prend beaucoup de temps dans un script entier, est d'utiliser:

  • L'extension Xdebug , permettant de générer des données de profilage pour le script
  • Logiciel qui lit les données de profilage et vous présente quelque chose de lisible. J'en connais trois:
    • Webgrind ; interface Web ; devrait fonctionner sur n'importe quel serveur Apache + PHP
    • WinCacheGrind ; seulement sur les fenêtres
    • KCacheGrind ; probablement que Linux et linux-like; C'est celle que je préfère, d'ailleurs

Pour obtenir des fichiers de profilage, vous devez installer et configurer Xdebug; jetez un oeil à la page Profil PHP Scripts de la documentation.

Ce que je fais généralement n’est pas d’activer le profileur par défaut (il génère des fichiers assez gros et ralentit le travail), mais utilise la possibilité d’envoyer un paramètre appelé XDEBUG_PROFILE en tant que données GET, pour activer le profilage uniquement pour la page dont j'ai besoin.
La partie de mon php.ini relative au profilage ressemble à ceci:

xdebug.profiler_enable = 0              ; Profiling not activated by default
xdebug.profiler_enable_trigger = 1      ; Profiling activated when requested by the GET parameter
xdebug.profiler_output_dir = /tmp/ouput_directory
xdebug.profiler_output_name = files_names

(Lisez la documentation pour plus d'informations)

Cette capture d'écran provient d'un programme C++ dans KcacheGrind: http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif
(source: sourceforge.net )

Vous obtiendrez exactement le même genre de chose avec PHP scripts ;-)
(Avec KCacheGrind, je veux dire; WinCacheGrind n’est pas aussi bon que KCacheGrind ...)

Cela vous permet d’avoir une bonne vue de ce qui prend du temps dans votre application - et il est parfois utile de localiser la fonction qui ralentit tout ^. ^

Notez que Xdebug compte le temps CPU passé par PHP; quand PHP attend une réponse d'une base de données (par exemple), il ne fonctionne pas; uniquement Xdebug pensera donc que la demande de base de données ne prend pas beaucoup de temps!
Cela devrait être profilé sur le serveur SQL, pas PHP, donc ...


J'espère que cela vous aidera :-)
S'amuser !

176
Pascal MARTIN

Pour des choses rapides, je fais ceci (en PHP):

$startTime = microtime(true);
doTask(); // whatever you want to time
echo "Time:  " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";

Vous pouvez également utiliser un profileur tel que http://xdebug.org/ .

37
Scott Saunders

J'ai fait un cours de chronométrage simple, peut-être utile pour quelqu'un:

class TimingHelper {

    private $start;

    public function __construct() {
        $this->start = microtime(true);
    }

    public function start() {
        $this->start = microtime(true);
    }

    public function segs() {
        return microtime(true) - $this->start;
    }

    public function time() {
        $segs = $this->segs();
        $days = floor($segs / 86400);
        $segs -= $days * 86400;
        $hours = floor($segs / 3600);
        $segs -= $hours * 3600;
        $mins = floor($segs / 60);
        $segs -= $mins * 60;
        $microsegs = ($segs - floor($segs)) * 1000;
        $segs = floor($segs);

        return 
            (empty($days) ? "" : $days . "d ") . 
            (empty($hours) ? "" : $hours . "h ") . 
            (empty($mins) ? "" : $mins . "m ") . 
            $segs . "s " .
            $microsegs . "ms";
    }

}

Utilisation:

$th = new TimingHelper();
<..code being mesured..>
echo $th->time();
$th->start(); // if it's the case
<..code being mesured..>
echo $th->time();

// result: 4d 17h 34m 57s 0.00095367431640625ms 
8
Nelson Teixeira

Voici une réponse directe à votre question

existe-t-il un logiciel pour mesurer cela?

Oui il y a. Je me demande pourquoi quelqu'un ne l'a pas encore mentionné. Bien que les réponses suggérées ci-dessus semblent bien pour un contrôle rapide, elles ne sont toutefois pas évolutives à long terme ou pour un projet plus important.

Pourquoi ne pas utiliser un outil APM (Application Performance Monitoring) spécialement conçu pour cela, et bien plus encore. Découvrez NewRelic, AppDynamics, Ruxit (tous ont une version gratuite) pour surveiller le temps d'exécution, l'utilisation des ressources, le débit de chaque application au niveau de la méthode.

8
na-98

Si vous souhaitez tester rapidement les performances d'un framework, vous pouvez placer le fichier index.php

//at beginning
$milliseconds = round(microtime(true) * 1000);

//and at the end
echo round(microtime(true) * 1000) - $milliseconds;

Chaque fois que vous obtiendrez le temps d'exécution en millisecondes. Parce que les microsecondes ne sont pas très utiles pour tester un cas de structure.

5
tasmaniski

J'utilise XHProf dernièrement http://pecl.php.net/package/xhprof . Il a été développé à l'origine par Facebook et est livré avec une interface Web décente.

4
Jason

Je voudrais partager avec vous une fonction que j'ai utilisée pour mesurer la vitesse de toute fonction existante, jusqu'à 10 arguments:

function fdump($f_name='', $f_args=array()){

    $f_dump=array();
    $f_result='';

    $f_success=false;

    $f_start=microtime();
    $f_start=explode(' ', $f_start);
    $f_start=$f_start[1] + $f_start[0];

    if(function_exists($f_name)){

        if(isset($f_args[0])&&is_array($f_args[0])){
            if($f_result=$f_name($f_args)){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[1])){
            if($f_result=$f_name($f_args[0])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[2])){
            if($f_result=$f_name($f_args[0],$f_args[1])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[3])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[4])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[5])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[6])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[7])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[8])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[9])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[10])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8],$f_args[9])){
                $f_success=true;
            }
        }
    }
    $f_end=microtime();
    $f_end=explode(' ', $f_end);
    $f_end=$f_end[1] + $f_end[0];

    $f_time=round(($f_end - $f_start), 4);
    $f_dump['f_success']=$f_success;
    $f_dump['f_time']=$f_time;
    $f_dump['f_result']=$f_result;

    var_dump($f_dump);exit;

    //return $f_result;

}

Exemple

function do_stuff($arg1='', $arg2=''){
    return $arg1.' '.$arg2;
}

fdump('do_stuff',array('hello', 'world'));

Résultats

  array(3) {
    ["f_success"]=>
    bool(true)
    ["f_time"]=>
    float(0)            //too fast...
    ["f_result"]=>
    string(11) "hello world"
  }
3
RafaSashi

Si c'est quelque chose qui peut être testé en dehors du contexte Web, j'utilise simplement la commande Unix time.

2
chaos

Zend Studio prend en charge le profilage à l'aide de XDebug ou de ZendDebugger. Il va profiler votre code, en vous disant exactement combien de temps chaque fonction a pris. C'est un outil fantastique pour déterminer où se trouvent vos goulots d'étranglement.

2
OverloadUT

Vous pouvez utiliser des éléments de base, tels que stocker des horodatages ou microtime () avant et après une opération, pour calculer le temps nécessaire. C'est facile à faire, mais pas très précis. Peut-être une meilleure solution est Xdebug , je n’ai jamais travaillé avec elle mais cela semble être le plus connu PHP débogueur/profileur que je puisse trouver.

0
Alex