Manière la plus simple de profiler un script PHP

289

Quelle est la façon la plus simple de profiler un script PHP?

J'adorerais ajouter quelque chose qui me montre un vidage de tous les appels de fonction et combien de temps ils ont pris, mais je suis également d'accord pour mettre quelque chose autour de fonctions spécifiques.

J'ai essayé d'expérimenter la fonction microtime :

$then = microtime();
myFunc();
$now = microtime();

echo sprintf("Elapsed:  %f", $now-$then);

mais cela me donne parfois des résultats négatifs. De plus, c'est beaucoup de mal à saupoudrer cela sur tout mon code.

Mark Biek
la source
7
hey Mark, consultez ce commentaire pour vous aider à résoudre les commentaires négatifs: ro.php.net/manual/en/function.microtime.php#99524
Mina
16
Ce commentaire lié par @Midiane n'a pas de sens. Si cela semblait résoudre le problème du commentateur, ce devait être une coïncidence. Juste à l' aide microtime()conduira à l' évaluation des expressions comme parfois: "0.00154800 1342892546" - "0.99905700 1342892545", qui évaluera comme: 0.001548 - 0.999057. Vous pouvez utiliser microtime( TRUE )pour éviter ce problème, comme l'a souligné @luka.
JMM

Réponses:

104

L' extension PECL APD est utilisée comme suit:

<?php
apd_set_pprof_trace();

//rest of the script
?>

Ensuite, analysez le fichier généré à l'aide de pprofp.

Exemple de sortie:

Trace for /home/dan/testapd.php
Total Elapsed Time = 0.00
Total System Time  = 0.00
Total User Time    = 0.00


Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
100.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0009            0 main
56.9 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0005   0.0005            0 apd_set_pprof_trace
28.0 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 preg_replace
14.3 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 str_replace

Avertissement: la dernière version d'APD est datée de 2004, l'extension n'est plus maintenue et présente divers problèmes de compatibilité (voir commentaires).

Vincent
la source
19
L'extension APD est cassée sur php 5.4.
Skynet
En réponse à user457015, j'ai pu le faire fonctionner sur un site Web exécutant wordpress 3.8.1 et PHP 5.3.10 et cela semblait fonctionner très bien.
Supernovah
1
@Supernovah, user457015 a dit PHP 5.4. Il n'a pas dit qu'il était cassé en PHP 5.3.
magnus
@ user1420752 J'utilise 5.3.27 et il n'y fonctionne pas également. J'obtiens une erreur de fonction non définie.
Fractaly
2
La dernière version d'APD date de 2004 (!) Elle ne fonctionne pas avec PHP 7. Lorsque vous essayez d'installer pour PHP 5 avec pecl install apd, elle donne un message d'erreur sur "config.m4". Il semble que vous devez l'installer à partir des sources, ce que je n'ai pas encore essayé. Sérieusement, n'y a-t-il pas un outil de profilage CLI moderne et mis à jour pour PHP qui s'installe avec Homebrew, nécessite une configuration minimale et donne une sortie facilement lisible par l'homme?
avaline
267

Tu veux xdebug je pense. Installez-le sur le serveur, allumez-le, pompez la sortie via kcachegrind (pour linux) ou wincachegrind (pour windows) et il vous montrera quelques jolis graphiques qui détaillent les horaires exacts, les nombres et l'utilisation de la mémoire (mais vous besoin d'une autre extension pour cela).

Ça berce, sérieusement: D

mercutio
la source
6
J'ai trouvé cela beaucoup plus facile à mettre en œuvre que la solution APD. Mais c'est peut-être parce que pour une raison quelconque, APD ne s'est pas compilé correctement sur mon système. Les graphiques de kcachegrind étaient aussi jolis que promis.
wxs
1
@EvilPuppetMaster, vous devez compiler php avec --enable-memory-limit ou utiliser une version php plus moderne. Voir xdebug.org/docs/basic#xdebug_memory_usage
mercutio
52
xdebug + webgrind est rapidement devenu mon arme de choix pour un profilage rapide et facile. code.google.com/p/webgrind
xkcd150
6
xdebug + xdebug_start_trace () + xdebug_stop_trace () = win
quano
3
C'était très facile de travailler sur Windows avec XAMPP. Netbeans avait déjà été configuré pour xdebug. La seule chose que vous devez faire est de changer un paramètre xdebug dans php.ini en xdebug.profiler_output_name = "cachegrind.out.% T-% s" sinon aucune sortie ne sera générée. Nécessite le redémarrage d'Apache.
beginner_
97

Aucune extension n'est nécessaire, utilisez simplement ces deux fonctions pour un profilage simple.

// Call this at each point of interest, passing a descriptive string
function prof_flag($str)
{
    global $prof_timing, $prof_names;
    $prof_timing[] = microtime(true);
    $prof_names[] = $str;
}

// Call this when you're done and want to see the results
function prof_print()
{
    global $prof_timing, $prof_names;
    $size = count($prof_timing);
    for($i=0;$i<$size - 1; $i++)
    {
        echo "<b>{$prof_names[$i]}</b><br>";
        echo sprintf("&nbsp;&nbsp;&nbsp;%f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
    }
    echo "<b>{$prof_names[$size-1]}</b><br>";
}

Voici un exemple, appelant prof_flag () avec une description à chaque point de contrôle, et prof_print () à la fin:

prof_flag("Start");

   include '../lib/database.php';
   include '../lib/helper_func.php';

prof_flag("Connect to DB");

   connect_to_db();

prof_flag("Perform query");

   // Get all the data

   $select_query = "SELECT * FROM data_table";
   $result = mysql_query($select_query);

prof_flag("Retrieve data");

   $rows = array();
   $found_data=false;
   while($r = mysql_fetch_assoc($result))
   {
       $found_data=true;
       $rows[] = $r;
   }

prof_flag("Close DB");

   mysql_close();   //close database connection

prof_flag("Done");
prof_print();

La sortie ressemble à ceci:

Démarrer
   0,004303
Se connecter à la base de données
   0,003518
Effectuer la requête
   0,000308
Récupérer les données
   0,000009
Fermer la base de données
   0,000049
Terminé

TimH - Codidact
la source
37

Cross poster ma référence à partir de la version bêta de la documentation SO qui est hors ligne.

Profilage avec XDebug

Une extension de PHP appelée Xdebug est disponible pour aider au profilage des applications PHP , ainsi qu'au débogage d'exécution. Lors de l'exécution du profileur, la sortie est écrite dans un fichier au format binaire appelé "cachegrind". Des applications sont disponibles sur chaque plateforme pour analyser ces fichiers. Aucune modification du code d'application n'est nécessaire pour effectuer ce profilage.

Pour activer le profilage, installez l'extension et ajustez les paramètres php.ini. Certaines distributions Linux sont livrées avec des packages standard (par exemple le php-xdebugpackage d'Ubuntu ). Dans notre exemple, nous exécuterons le profil facultativement en fonction d'un paramètre de demande. Cela nous permet de garder les paramètres statiques et d'activer le profileur uniquement si nécessaire.

# php.ini settings
# Set to 1 to turn it on for every request
xdebug.profiler_enable = 0
# Let's use a GET/POST parameter to turn on the profiler
xdebug.profiler_enable_trigger = 1
# The GET/POST value we will pass; empty for any value
xdebug.profiler_enable_trigger_value = ""
# Output cachegrind files to /tmp so our system cleans them up later
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_output_name = "cachegrind.out.%p"

Utilisez ensuite un client Web pour faire une demande à l'URL de votre application que vous souhaitez profiler, par exemple

http://example.com/article/1?XDEBUG_PROFILE=1

Au fur et à mesure que la page traite, elle écrit dans un fichier avec un nom similaire à

/tmp/cachegrind.out.12345

Par défaut, le numéro dans le nom de fichier est l'identifiant du processus qui l'a écrit. Ceci est configurable avec lexdebug.profiler_output_name paramètre.

Notez qu'il écrira un fichier pour chaque requête / processus PHP exécuté. Ainsi, par exemple, si vous souhaitez analyser une publication de formulaire, un profil sera écrit pour la demande GET pour afficher le formulaire HTML. Le paramètre XDEBUG_PROFILE devra être passé dans la demande POST suivante pour analyser la deuxième demande qui traite le formulaire. Par conséquent, lors du profilage, il est parfois plus facile d'exécuter curl pour POSTER directement un formulaire.

Analyse de la sortie

Une fois écrit, le cache de profil peut être lu par une application telle que KCachegrind ou Webgrind . PHPStorm, un IDE PHP populaire, peut également afficher ces données de profilage .

KCachegrind

KCachegrind, par exemple, affichera des informations, notamment:

  • Fonctions exécutées
  • Temps d'appel, à la fois lui-même et incluant les appels de fonction ultérieurs
  • Nombre de fois que chaque fonction est appelée
  • Graphiques d'appel
  • Liens vers le code source

Ce qu'il faut chercher

De toute évidence, l'optimisation des performances est très spécifique aux cas d'utilisation de chaque application. En général, il est bon de rechercher:

  • Appels répétés à la même fonction que vous ne vous attendez pas à voir. Pour les fonctions qui traitent et interrogent les données, cela pourrait être une excellente opportunité pour votre application de mettre en cache.
  • Fonctions à fonctionnement lent. Où l'application passe-t-elle la plupart de son temps? le meilleur gain dans l'optimisation des performances se concentre sur les parties de l'application qui consomment le plus de temps.

Remarque : Xdebug, et en particulier ses fonctionnalités de profilage, sont très gourmandes en ressources et ralentissent l'exécution PHP. Il est recommandé de ne pas les exécuter dans un environnement de serveur de production.

Matt S
la source
3
Ajout à la liste d'outils pour analyser le cache de profil: PhpStorm dispose également d'un outil pour prévisualiser le cache de profil
peterchaula
1
@peter J'ai oublié que PHPStorm a cette fonctionnalité. Je l'ai ajouté avec un lien vers la documentation. Merci!
Matt S
Est-il possible d'obtenir un rapport texte (non GUI) directement sur le serveur?
Alexander Shcheblikin
1
@Mark pourriez-vous marquer cela comme la réponse, s'il vous plaît. La réponse actuelle était obsolète même lorsqu'elle a été publiée et n'a pas fonctionné depuis de nombreuses années. Cela fonctionne, et je ne connais pas de meilleure méthode.
Mawg dit réintégrer Monica le
24

Si la soustraction de microtimes vous donne des résultats négatifs, essayez d'utiliser la fonction avec l'argument true( microtime(true)). Avec true, la fonction renvoie un flottant au lieu d'une chaîne (comme elle le fait si elle est appelée sans arguments).

luka
la source
24

Honnêtement, je vais faire valoir que l'utilisation de NewRelic pour le profilage est la meilleure.

C'est une extension PHP qui ne semble pas du tout ralentir le temps d'exécution et ils font la surveillance pour vous, permettant une exploration décente. Dans la version onéreuse, ils permettent une analyse approfondie (mais nous ne pouvons pas nous permettre leur modèle de tarification).

Pourtant, même avec le plan gratuit / standard, il est évident et simple où la plupart des fruits suspendus sont. J'aime aussi le fait que cela puisse aussi vous donner une idée sur les interactions DB.

capture d'écran de l'une des interfaces lors du profilage

zeroasterisk
la source
16
New Relic semble prometteur, bien sûr. Cependant, la partie «Divulgation de vos données d'application» de leur politique de confidentialité m'a repoussé instantanément. À mon humble avis, partager des morceaux de code source propriétaire avec des tiers est un peu trop.
Cengiz Can
8
Ne sautez pas à leur défense ici, mais il semble que "Application Data" ne soit que des informations sur les performances et des informations de configuration du système, pas le code source de votre application.
David Shields
Sap ma nouvelle relique montre ma "WebTransaction" comme 99% du temps, et n'a pas le compte pro pour "ApplicationTraces"
Karthik T
1
essayez de vous inscrire à: newrelic.com/rackspace <devrait vous donner "standard" gratuitement
zeroasterisk
15

Profilage du pauvre, aucune extension requise. Prend en charge les profils imbriqués et le pourcentage du total:

function p_open($flag) {
    global $p_times;
    if (null === $p_times)
        $p_times = [];
    if (! array_key_exists($flag, $p_times))
        $p_times[$flag] = [ 'total' => 0, 'open' => 0 ];
    $p_times[$flag]['open'] = microtime(true);
}

function p_close($flag)
{
    global $p_times;
    if (isset($p_times[$flag]['open'])) {
        $p_times[$flag]['total'] += (microtime(true) - $p_times[$flag]['open']);
        unset($p_times[$flag]['open']);
    }
}

function p_dump()
{
    global $p_times;
    $dump = [];
    $sum  = 0;
    foreach ($p_times as $flag => $info) {
        $dump[$flag]['elapsed'] = $info['total'];
        $sum += $info['total'];
    }
    foreach ($dump as $flag => $info) {
        $dump[$flag]['percent'] = $dump[$flag]['elapsed']/$sum;
    }
    return $dump;
}

Exemple:

<?php

p_open('foo');
sleep(1);
p_open('bar');
sleep(2);
p_open('baz');
sleep(3);
p_close('baz');
sleep(2);
p_close('bar');
sleep(1);
p_close('foo');

var_dump(p_dump());

Rendements:

array:3 [
  "foo" => array:2 [
    "elapsed" => 9.000766992569
    "percent" => 0.4736904954747
  ]
  "bar" => array:2 [
    "elapsed" => 7.0004580020905
    "percent" => 0.36841864946596
  ]
  "baz" => array:2 [
    "elapsed" => 3.0001420974731
    "percent" => 0.15789085505934
  ]
]
évêque
la source
13

PECL XHPROF semble également intéressant. Il a une interface HTML cliquable pour afficher les rapports et une documentation assez simple . Je dois encore le tester.

Josef Sábl
la source
On dirait que ça ne reçoit pas beaucoup d'amour. Dernière mise à jour en 2009, pas de packages PEAR pour 5.3, 5.4 et au-delà ...
dland
1
Facebook a créé une fourchette avec support via php 5.5 github.com/facebook/xhprof
borkencode
Consultez également cette fourchette qui propose quelques ajustements supplémentaires: github.com/preinheimer/xhprof
Fedir RYKHTIK
xhprof.io fournit une interface graphique pour les données collectées à l'aide de XHProf, ainsi que la possibilité de stocker des données dans la base de données à des fins d'analyse historique. Je suis l'auteur de cette dernière implémentation.
Gajus
10

J'aime utiliser phpDebug pour le profilage. http://phpdebug.sourceforge.net/www/index.html

Il génère toute l'utilisation du temps / de la mémoire pour tout SQL utilisé ainsi que tous les fichiers inclus. De toute évidence, cela fonctionne mieux sur du code abstrait.

Pour le profilage des fonctions et des classes, je vais simplement utiliser microtime()+ get_memory_usage()+ get_peak_memory_usage().

Eric Lamb
la source
6

Pour l'analyse comparative, comme dans votre exemple, j'utilise le package pear Benchmark . Vous définissez des marqueurs pour mesurer. La classe fournit également quelques assistants de présentation, ou vous pouvez traiter les données comme bon vous semble.

Je l'ai en fait enveloppé dans une autre classe avec une méthode __destruct. Lorsqu'un script se termine, la sortie est enregistrée via log4php dans syslog, j'ai donc beaucoup de données de performance à partir desquelles je peux travailler.

Gary Richardson
la source
3

XDebug n'est pas stable et n'est pas toujours disponible pour une version php particulière. Par exemple, sur certains serveurs, je lance toujours php-5.1.6, - c'est ce qui vient avec RedHat RHEL5 (et btw reçoit toujours des mises à jour pour tous les problèmes importants), et le récent XDebug ne compile même pas avec ce php. J'ai donc fini par passer au débogueur DBG. Son benchmark php fournit le timing des fonctions, des méthodes, des modules et même des lignes.

user2221743
la source
2

Vous devriez certainement vérifier ce nouveau profileur php.

https://github.com/NoiseByNorthwest/php-spx

Il redéfinit la façon dont les profileurs php collectent et présentent le résultat. Au lieu de générer uniquement un nombre total d'appels de fonction particuliers et le temps total passé à l'exécuter - PHP-SPX présente l'intégralité de la chronologie de l'exécution de la demande d'une manière parfaitement lisible. Voici l'écran de l'interface graphique qu'il fournit.

entrez la description de l'image ici

Jacek Dziurdzikowski
la source