php-memprof est une extension de profilage de mémoire rapide et précise pour PHP qui peut être utilisée pour trouver la cause des fuites de mémoire.
L'extension suit l'allocation et la libération de blocs de mémoire pour signaler la quantité de mémoire perdue par chaque fonction, méthode ou fichier d'un programme.
Signale la mémoire non libérée à des points arbitraires du programme
Vide le profil aux formats callgrind, pprof ou raw array
Peut suivre la mémoire allouée par PHP lui-même ainsi que par malloc natif
php-memprof dépend de libjudy et de sys/queue.h.
Sur les distributions basées sur Debian, les dépendances peuvent être installées avec :
# Debian or Ubuntu: apt install libjudy-dev
Sur Alpine :
# Alpine apk add judy-dev bsd-compat-headers
Sur MacOS :
# install libjudy dependency: brew install traildb/judy/judy
Assurez-vous d'installer les dépendances, puis :
pecl install memprof
Sous MacOS : JUDY_DIR=$(brew --prefix traildb/judy/judy) pecl install memprof
Remarque Si libjudy est installé dans un chemin non standard (pas /usr ou /usr/local), veuillez utiliser la méthode d'installation manuelle ci-dessous.
Assurez-vous d'installer les dépendances, puis :
Téléchargez la source et exécutez les commandes suivantes dans le répertoire source :
phpize ./configure make make install
Remarque Si libjudy est installé dans un chemin non standard (pas /usr ou /usr/local), vous pouvez le spécifier comme ceci :
./configure --with-judy-dir=/opt/homebrew/Cellar/judy/1.0.5
Les utilisateurs d'Arch Linux préféreront peut-être installer le package non officiel php-memprof avec makepkg
ou leur assistant AUR préféré. Si vous utilisez yay
, par exemple :
yay -S php-memprof
Veuillez signaler tout problème avec ce package sur sa page AUR.
L'extension peut être chargée en ligne de commande, juste pour un seul script :
php -dextension=memprof.so script.php
Ou en permanence, dans php.ini :
extension=memprof.so
L'extension n'a aucune surcharge lorsqu'elle n'est pas profilée, elle peut donc être chargée par défaut sur les environnements de développement.
La manière la plus simple d'utiliser memprof
est de le laisser enregistrer le profil de mémoire lorsque la limite de mémoire du programme est dépassée.
dump_on_limit
Le profilage en mode dump_on_limit
est activé au démarrage de la requête lorsque l'un des éléments suivants est vrai :
La variable d'environnement MEMPROF_PROFILE
est égale à dump_on_limit
$_GET["MEMPROF_PROFILE"]
est égal à dump_on_limit
$_POST["MEMPROF_PROFILE"]
est égal à dump_on_limit
Pour les scripts de ligne de commande, nous pouvons définir la variable d'environnement :
MEMPROF_PROFILE=dump_on_limit php test.php
Pour les scripts Web, nous pouvons définir la variable $_GET
:
curl http://127.0.0.1/test.php?MEMPROF_PROFILE=dump_on_limit
Ou la variable $_POST
:
curl -d MEMPROF_PROFILE=dump_on_limit http://127.0.0.1/test.php
Remarque La fonction
memprof_enabled_flags()
peut être appelée pour vérifier si le profilage est actuellement activé en modedump_on_limit
.
Dans ce mode, memprof
enregistrera automatiquement le profil si le programme dépasse la limite de mémoire (lorsque PHP déclenche une erreur comme Fatal error: Allowed memory size of 15728640 bytes exhausted (tried to allocate 1024 bytes)
).
Par défaut, le profil est enregistré dans un fichier nommé memprof.callgrind.*
dans /tmp
ou C:WindowsTemp
.
La méthode recommandée pour visualiser le résultat est d'utiliser Kcachegrind (sous Linux) ou Qcachegrind (sous MacOS, Windows). Les outils Google Perftools sont également pris en charge. Voir la documentation de memprof_dump_callgrind()
et de ses variantes.
La plupart des distributions ont un package kcachegrind
prêt à être installé.
Par exemple, Ubuntu ou Debian :
sudo apt install kcachegrind
D'autres distributions ont très probablement également un package prêt à être installé.
Utilisez Homebrew : https://formulae.brew.sh/formula/qcachegrind
Téléchargez-le depuis https://sourceforge.net/projects/qcachegrindwin/
Le profilage est activé au démarrage de la demande lorsque l'un des éléments suivants est vrai :
La variable d'environnement MEMPROF_PROFILE
n'est pas vide
$_GET["MEMPROF_PROFILE"]
n'est pas vide
$_POST["MEMPROF_PROFILE"]
n'est pas vide
La variable MEMPROF_PROFILE
accepte une liste d'indicateurs séparés par des virgules.
Exemples de valeurs MEMPROF_PROFILE
valides :
1
: non vide : le profilage est activé
dump_on_limit
: le profilage est activé, le dump sera effectué en fonction de la limite de mémoire
native
: le profilage est activé, profilera les allocations natives
dump_on_limit,native
: le profilage est activé, profilera les allocations natives, videra la limite de mémoire
Liste des drapeaux valides :
dump_on_limit
: videra le profil au format callgrind dans /tmp
ou C:WindowsTemp
. Le répertoire de sortie peut être modifié avec le paramètre ini memprof.output_dir
.
native
: profilera les allocations natives malloc()
, pas seulement celles de PHP (ce n'est pas thread-safe, voir ci-dessous).
Memprof ne suit pas les allocations natives par défaut, mais cela peut être activé en définissant MEMPROF_PROFILE
sur native
.
Les allocations natives sont les allocations effectuées en dehors du propre allocateur de mémoire de PHP. Généralement, les bibliothèques externes telles que libxml2 (utilisées dans l'extension DOM) effectuent des allocations natives. PHP peut également effectuer des allocations natives pour les ressources persistantes.
L'activation du suivi des allocations natives profilera ces allocations en plus des propres allocations de PHP.
Notez que lorsque le suivi natif est activé, le programme plantera si une bibliothèque native utilise des threads, car les hooks sous-jacents ne sont pas thread-safe.
Le format du fichier de sortie est défini avec le paramètre ini memprof.output_format
. Les options sont :
callgrind
(par défaut)
pprof
Remarque : cela ne peut être disponible que lorsque l'extension est construite à partir des sources (et non installée avec pecl), à partir du #101.
Indique si le profilage de la mémoire est actuellement activé (voir ci-dessus).
Indique si le profilage de la mémoire et quelles fonctionnalités de profilage sont activées (voir ci-dessus).
Vide le profil actuel au format callgrind. Le résultat peut être visualisé avec des outils tels que KCacheGrind ou QCacheGrind.
<phpmemprof_dump_callgrind(fopen("output", "w"));
Voici une capture d'écran de QcacheGrind :
Vide le profil actuel au format pprof.
<?phpmemprof_dump_pprof(fopen("profile.heap", "w"));
Le fichier peut être visualisé avec l'outil pprof
de google-perftools. (Voir ci-dessous pour les instructions d'installation.)
Afficher le graphique d'appel annoté dans le navigateur Web ou dans gv
:
$ pprof --web profile.heap $ # or: $ pprof --gv profile.heap
Afficher une ligne par fonction, triée selon sa propre utilisation de la mémoire :
$ pprof --text profile.heap
pprof
: Ubuntu : apt install google-perftools
. Sur Ubuntu, l'outil s'appelle google-pprof
, vous devez donc remplacer pprof
par google-pprof
dans les exemples ci-dessus.
Renvoie un tableau représentant le profil actuel.
<php$dump = memprof_dump_array();
Le tableau expose les informations suivantes :
Mémoire inclusive et exclusive divulguée par les fonctions (en comptant uniquement la mémoire qui n'est toujours pas libérée lorsque memprof_dump_array est appelé)
Nombre de blocs inclusifs et exclusifs de fonctions (nombre d'allocations ; en comptant uniquement les blocs qui ne sont toujours pas libérés lorsque memprof_dump_array est appelé)
Les données sont présentées dans des piles d'appels. De cette façon, si une fonction est appelée depuis plusieurs endroits, il est possible de voir quel chemin d'appel a provoqué la fuite de mémoire la plus importante.
Array ( [memory_size] => 11578 [blocks_count] => 236 [memory_size_inclusive] => 10497691 [blocks_count_inclusive] => 244 [calls] => 1 [called_functions] => Array ( [main] => Array ( [memory_size] => 288 [blocks_count] => 3 [memory_size_inclusive] => 10486113 [blocks_count_inclusive] => 8 [calls] => 1 [called_functions] => Array ( [a] => Array ( [memory_size] => 4 [blocks_count] => 1 [memory_size_inclusive] => 10485825 [blocks_count_inclusive] => 5 [calls] => 1 [called_functions] => Array ( [b] => Array ( [memory_size] => 10485821 [blocks_count] => 4 [memory_size_inclusive] => 10485821 [blocks_count_inclusive] => 4 [calls] => 1 [called_functions] => Array ( [str_repeat] => Array ( [memory_size] => 0 [blocks_count] => 0 [memory_size_inclusive] => 0 [blocks_count_inclusive] => 0 [calls] => 1 [called_functions] => Array ( ) ) ) ) ) ) [memprof_dump_array] => Array ( [memory_size] => 0 [blocks_count] => 0 [memory_size_inclusive] => 0 [blocks_count_inclusive] => 0 [calls] => 1 [called_functions] => Array ( ) ) ) ) ) )
Renvoie la version de l'extension sous forme de chaîne. La version peut être comparée avec version_compare().
Les extensions peuvent entrer en conflit avec xdebug, blackfire ou d'autres extensions. Si tel est votre cas, merci de le signaler.
La branche actuelle prend en charge PHP 7.1 à PHP 8.
La branche php5 prend en charge PHP 5.
Voir INTERNES.md