En effet, PHP est un langage qui ne permet pas au développeur de gérer lui-même la mémoire utilisée par son code.
C’est en effet ce que l’on appelle dans le monde des langages de programmation le garbage collector
qui se charge de gérer la mémoire requise par le fonctionnement du code de manière optimum (du moins en théorie).
Et si le développeur a bien la possibilité d’altérer son comportement à l’aide des fonctions gc_*
, elles ne sont utiles que dans un contexte très particulier et en conséquence elles n’autorisent en aucune façon une gestion fine de la mémoire similaire à celle que permet un langage comme le C.
Dans un tel contexte, il est donc complètement inutile de connaître la quantité de mémoire requise pour le stockage d’une structure zval
ou de toute autre structure manipulée par PHP en interne, car vous ne pourrez rien faire pour optimiser la façon dont le langage utilise cette mémoire (à moins que vous ne souhaitiez briller en société en étalant votre science, encore que je pense que ce genre d’information ne passionne pas les foules).
Au mieux, vous pouvez faire des appels à unset()
à des endroits stratégiques de votre code pour indiquer au « garbage collector » que vous n’avez plus besoin d’une variable et qu’en conséquence il peut faire le ménage.
Il est par exemple parfois pertinent de le faire à l’issue d’une boucle foreach
, puisque la variable dans laquelle sont stockées les différentes variables du tableau ou de l’objet sur laquelle la boucle est effectuée n’est pas détruite automatiquement à l’issue de la boucle.
<?php foreach ($anArrayWithBiGobjectInIt as $anObject) { // do something with $anObject } // $anObject contient le dernier objet du tableau $anArrayWithBiGobjectInIt. // Il est donc pertinent de demander sa destruction unset($anObject) ?>
Cependant, vous n’aurez aucune garantie que la mémoire utilisée sera effectivement libérée lors de l’appel à unset()
.
En effet, la mémoire ne sera libérée que lorsqu’il n’y aura plus de référence vers la variable concernée, et même si c’est le cas, le garbage collector
ne libérera peut-être pas l’espace mémoire correspondant immédiatement afin d’optimiser la gestion globale de la mémoire.
De plus, d’une version de PHP à une autre, le fonctionnement du garbage collector
peut être plus ou moins efficace.
Un même code peut donc avoir une empreinte mémoire qui évolue d’une manière totalement différente en fonction de la version de PHP utilisée.
Pour preuve, en moyenne, PHP 5.3 réduit significativement la consommation mémoire d’un script par rapport à 5.2, 5.4 PHP fait encore mieux en réduisant encore cette consommation mémoire de 30 % et la future version 5.5 semble prometteuse de ce point de vue.
Il est donc totalement illusoire et stupide d’espérer contrôler ou optimiser la façon dont PHP utilise la mémoire.
Et si vous décidez tout de même de le faire à l’aide du peu d’outils que PHP met à votre disposition, je peux vous dire par expérience (oui, il m’arrive aussi d’être stupide) que vous avez plus de chance d’empirer la situation que de l’améliorer.
Cependant, cela ne veut pas dire que vous ne pouvez rien faire pour éviter d’avoir une consommation de mémoire excessive.
En effet, si le langage ne vous permet pas d’optimiser la consommation mémoire de votre code, vous pouvez cependant faire en sorte que vos processus PHP aient une empreinte mémoire optimale et concevoir votre code de façon à réduire au maximum la quantité de mémoire requise pour son fonctionnement.
Ainsi, pour diminuer l’empreinte mémoire de vos processus PHP, vous pouvez notamment :
- Compiler PHP vous-même afin d’avoir un exécutable optimisé au maximum pour l’architecture sur laquelle il sera utilisé
- Supprimer toutes les extensions qui ne sont pas absolument indispensables au fonctionnement de votre code.
- Utiliser la version la plus récente possible en fonction de votre contexte technique.
Et au niveau de votre code, vous pouvez par exemple :
- Faire appel à
unset()
lorsque c’est utile, comme nous l’avons vu précédemment afin d’aider legarbage collector
à faire son travail au mieux. - Utiliser un système d’autochargement de classe afin de ne faire interpréter à PHP que le code absolument nécessaire au fonctionnement de vos scripts.
- Découpler au maximum vos classes afin qu’elle n’ait qu’une et une seule responsabilité et pouvoir ainsi charger en mémoire uniquement le code strictement nécessaire pour répondre au besoin et ainsi éviter les classes fourre-tout.
- Mettre en œuvre l’algorithme le mieux adapté pour résoudre votre problème en évitant, par exemple, de charger intégralement en mémoire un fichier pouvant contenir un gros volume de données pour l’interpréter.
- Ne pas transférer l’intégralité des enregistrements de votre serveur de base de données vers PHP lorsque cela est possible.
- Éviter dans la mesure du possible les appels récursifs qui peuvent se révéler très gourmands en mémoire.
Évidemment, toutes ces solutions sont cumulables et si malgré tout cela vous n’êtes pas satisfait de la consommation mémoire de vos scripts, il vous faudra soit ajouter des barrettes de mémoire dans vos machines ou abandonner PHP et recourir à un langage plus efficace de ce point de vue ou vous permettant effectivement de la gérer !
10 réactions
1 De Blanchon Vincent - 08/02/2013, 10:05
Tu es un peu dur avec l'article, je pense que le but est pas de nous dire de compter chaque octet utilisé, mais plutôt pour faire découvrir les dessous de PHP (ou une toute petite partie) à tout ceux qui n'ont pas le temps ou les compétences pour le découvrir
2 De Julien VINAI - 08/02/2013, 10:14
Tu ne peux pas cracher sur la foule en indiquant "à moins que vous ne souhaitiez briller en société en étalant votre science" et puis le faire derrière...
Quoi qu'il en soit je trouve le sujet intéressant et ta vision aussi. Ce qui est malheureux au final c'est que PHP soit aussi peu pilotable ... Mais il y a tellement de choses à optimiser en dehors de la mémoire que cela reste jouable : requêtes SQL, nombre d'appels à une fonction, suppression de boucles infinies (ah ah) ...
3 De nico - 08/02/2013, 10:19
Sur le sujet:
Compiler PHP vous-même afin d’avoir un exécutable optimisé au maximum pour l’architecture sur laquelle il sera utilisé
En pratique, c'est utilisé souvent sur les systèmes à fort traffic par exemple?
4 De mageekguy - 08/02/2013, 11:37
@Julien VINAI : gné ?
Parce que bon, entre parler d'un truc qui ne sert à rien et donner des conseils pratiques et utiles qui servent à quelque chose, il y a un monde, voir même un univers…
5 De mageekguy - 08/02/2013, 11:39
@nico : oui, c'est utilisé.
6 De mageekguy - 08/02/2013, 11:49
@Blanchon Vincent : À quoi bon faire découvrir des choses qui ne servent à rien dans le quotidien d'un développeur PHP ?
Autant j'aurais pu comprendre ce billet s'il avait été destiné à des développeurs souhaitant travailler sur le moteur de PHP, autant dans le contexte d'un utilisateur de PHP, il est totalement inutile.
7 De Lionel - 08/02/2013, 23:39
Je crois que quelqu'un ici c'est levé d'humeur assassine ce matin.
Ce n'est pas parce qu'une information n'a pas d'utilité industrielle pour soi qu'elle est stupide.
Je ne connaissais l'implémentation C d'une variable PHP. Bon. Savoir cette information ne va pas modifier ma façon de travailler, ni me faire briller en société, mais j'ai été content d'apprendre quelque chose, car cela à satisfait un peu de ma curiosité et la curiosité est une valeur importante pour un développeur.
8 De Seoxis - 09/02/2013, 01:19
En effet, PHP est un langage qui ne permet pas au développeur de gérer lui-même la mémoire utilisée par son code.
Même s'il ne la gère pas il peut optimiser son code afin de réduire celle-ci au minimum
Il y en a qui aime les codes bien structurés avec 1000 variables , bien sur mis dans des fichiers bien séparés alors que les inclusions bouffent la ram et pour couronner le tout chaque code possède son message d'erreur
Bref un gros pavé qui peut être synthétisé avec 10x moins de code ...
9 De lcallarec - 09/02/2013, 22:42
J'ai trouvé l'article original très intéressant (et les slides de la présentation sont très savants), bien plus que la pseudo-critique que l'on trouve ici, n'en déplaise à son auteur. Merci mageekguy pour le partage
Si tu as d'autres articles à descendre comme ça, tu peux faire preuve de tout le mépris que tu veux, ça ne me dérange pas vraiment (au plus, ça m'irrite méchant au bout de la seconde phrase et je vais pas plus loin), du moment que tu donnes le lien de l'article original !
10 De OPi - 11/02/2013, 10:39
À propos du garbage collector, le GNU/Linux Magazine France de ce mois ci
http://www.ed-diamond.com/feuille_l...
contient un article intitulé "La mort prochaine des ramasses-miettes ?".
L'idée (me semble-t-il pertinente) est que les quantités de mémoire croissants il ne sera plus "possible" d'avoir un garbage collector performant.