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


118

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

Réponses:


195

Vous avez (au moins) deux solutions:

Le plus "naïf" utilise microtime (vrai) pour avant et après une partie du code, pour obtenir le temps écoulé pendant son exécution; d'autres réponses disaient cela et donnaient déjà des exemples, donc je n'en dirai pas beaucoup plus.

C'est une bonne solution si vous voulez comparer quelques instructions; comme comparer deux types de fonctions, par exemple - c'est mieux si cela est fait 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 cela ne prend pas beaucoup de temps à mettre en place.



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 , pour 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 ; uniquement sous windows
    • KCacheGrind ; probablement seulement Linux et linux-like; C'est celui que je préfère, btw

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

Ce que je fais généralement, ce n'est pas d'activer le profileur par défaut (il génère des fichiers assez gros et ralentit les choses) , mais utilise la possibilité d'envoyer un paramètre appelé en XDEBUG_PROFILEtant que données GET, pour activer le profilage uniquement pour la page dont j'ai besoin.
La partie liée au profilage de mon php.ini 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

(Lire la documentation pour plus d'informations)

Cette capture d'écran provient d'un programme C ++ dans KcacheGrind: (source: sourceforge.net ) Vous obtiendrez exactement le même genre de chose avec les scripts PHP ;-) (Avec KCacheGrind, je veux dire; WinCacheGrind n'est pas aussi bon que KCacheGrind ... )http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif



Cela vous permet d'avoir une belle vue de ce qui prend du temps dans votre application - et cela aide parfois définitivement à localiser la fonction qui ralentit tout ^^

Notez que Xdebug compte le temps CPU passé par PHP; lorsque PHP attend une réponse d'une base de données (par exemple), cela ne fonctionne pas; attendre seulement. Donc Xdebug pensera que la requête DB ne prend pas beaucoup de temps!
Cela devrait être profilé sur le serveur SQL, pas sur PHP, donc ...


J'espère que cela vous sera utile :-)
Amusez-vous bien!


1
Une version Windows de QCacheGrind existe :-) sourceforge.net/projects/qcachegrindwin
François Breton

43

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 comme http://xdebug.org/ .


2
Pour plus de précision, je suggère (a) d'utiliser une boucle et de faire la moyenne du temps et (b) d'utiliser des fichiers séparés pour chaque chose que vous testez. Si vous avez plusieurs timings dans un même script, leur ordre peut parfois faire une différence.
DisgruntledGoat

9

J'ai fait un cours de chronométrage simple, peut-être que c'est utile à 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 

Vous avez echomal tapé: c'est , pas$echo
Di

9

Mise à jour 2020

Cela fait de nombreuses années que je n'ai pas répondu à ces questions pour la dernière fois, j'ai donc pensé que cela méritait une mise à jour sur le paysage APM.

  • AppDynamics a été acheté par Cisco et le compte gratuit pour toujours qu'ils offraient a été retiré de leur site Web.
  • NewRelic a baissé son prix de 149 $ / mois / hôte à 25 $ / mois / hôte pour rivaliser avec le nouveau venu sur le marché APM, Datadog qui offre 31 $ / mois / hôte.
  • Les fonctionnalités de Datadog APM sont encore légères et laissent beaucoup à désirer. Cependant, je les vois les améliorer et les améliorer tout au long de l'année prochaine.
  • Ruxit a été racheté par Dynatrace. Pas de choc ici car Ruxit est construit par d'anciens employés de Dynatrace. Cela a permis à Dynatrace de se transformer en un modèle véritablement SaaS pour mieux. Dites adieu à ce client Java volumineux si vous le souhaitez.
  • Il existe maintenant des options gratuites / open source. Commander Apache Skywalking qui est très populaire en Chine parmi leurs entreprises de haute technologie et PinPoint qui offre une démo que vous pouvez essayer avant d' installer. Ces deux éléments nécessitent que vous gériez l'hébergement, alors préparez-vous à lancer quelques machines virtuelles et à passer du temps avec l'installation et la configuration.
  • Je n'ai essayé aucune de ces solutions APM open source, je ne suis donc pas en mesure de les recommander, cependant, j'ai personnellement géré le déploiement de toutes ces solutions APM pour plusieurs organisations sur site ou sur le cloud pour des centaines d'applications / microservices. Je peux donc dire en toute confiance que vous ne pouvez pas vous tromper avec l'un des fournisseurs s'ils correspondent à votre facture.


Réponse initiale en octobre 2015

Voici une réponse directe à votre question

existe-t-il un logiciel pour mesurer cela?

Oui il y a. Je me demande pourquoi personne ne l'a encore mentionné. Bien que les réponses suggérées ci-dessus semblent bonnes pour une vérification rapide, mais ne sont 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.


6

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

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

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

Chaque fois, vous obtiendrez le temps d'exécution en millisecondes . Parce que les microsecondes ne sont pas trop utiles pour tester un cas de cadre.



4

Je voudrais partager avec vous une fonction que j'utilise 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'));

Retour

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

3

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


3

Zend Studio a intégré la prise en charge du profilage à l'aide de XDebug ou ZendDebugger. Il profilera votre code, vous indiquant exactement combien de temps chaque fonction a pris. C'est un outil fantastique pour déterminer où se trouvent vos goulots d'étranglement.


1

Vous pouvez utiliser des éléments de base comme le stockage 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 qu'une meilleure solution est Xdebug , je n'ai jamais travaillé avec mais il semble être le débogueur / profileur PHP le plus connu que je puisse trouver.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.