Dans le cadre d'applications web toujours plus complexes on est amené à écrire de gros traitements batch en PHP, le genre de traitements qui peuvent durer plusieurs heures.
C'est le cas pour www.bligg.fr, et la consommation de mémoire de ces scripts est vite devenue problématique : au fur et à mesure de leur exécution, la quantité de mémoire consommée explose, la mémoire semble subir des fuites / pertes importantes, et le script va jusqu'à dépasser la limite définie dans le php.ini.
Alors on augmente cette limite, mais le nombre de scripts augmente et la mémoire de la machine serait bien utile pour d'autres processus, tout se met a ramer et c'est la catastrophe.
Ainsi j'ai récemment décidé d'éradiquer ces fuites mémoires.
Pour cela, j'ai appliqué toutes les bonnes pratiques possibles dans ce domaine :
- Utiliser des mysql_free_result pour chaque resource mysql
- Faire un maximum de passages par référence
- Implémenter des destructeurs pour tous mes objets
- Faire des unset pour toutes les variables après leur utilisation
Malgré tout la consomation de mémoire des scripts continuait à augmenter au fur et à mesure de leur execution.
J'ai alors décidé de fliquer l'utilisation de mémoire avec des memory_get_usage à des endroits stratégiques. Et là surprise : les unset ne semblaient pas libérer la mémoire qu'ils auraient du, et la quantité de mémoire allouée augmentait à des endroits où elle n'aurait pas due.
J'ai essayé de remplacer les unset par des $var=null, mais le résultat n'était pas meilleur.
Après avoir farfouillé sur le net, j'ai appris que la version 5.3 de PHP, qui est en beta, dispose d'un garbage collector pour contourner ce problème.
N'écoutant que mon courage, je l'ai installé sur mon serveur, et là, oh miracle : au delà d'un certain palier, la consomation de mémoire n'augmente plus, le garbage collector fonctionne à merveille !
En ce qui concerne PHP 5.3 pour l'instant il ne m'a pas posé de problème (je ne l'ai pas pluggé sur apache, il sert juste pour les batchs). Juste un petit bug pour les accès mysql mais une magouille (ln -s /var/run/mysqld/mysqld.sock /tmp/mysql.sock) permet de le contourner.
Vous en saurez plus ici : http://qa.php.net/ et là : http://blog.pascal-martin.fr/post/php-5.3-installation-vmware-compilation-configuration
Dans l'ensemble c'est assez mal documenté mais on s'en sort.
La version stable est prévue pour mars je crois :)
Ma conclusion :
Inutile de se faire chier à essayer d'économiser la mémoire en PHP, dans la pratique ca ne fait aucune différence (tests à l'appui).
A la base PHP est fait pour générer des pages web, les scripts ne sont pas prévus pour durer plus de quelques secondes ; l'utilisation mémoire n'est donc pas un problème étant donné que tout est cleané en fin de script, et même en essayant d'utiliser des artifices on ne peut pas enrayer les fuites de mémoire.
La seule solution est donc d'utiliser PHP 5.3, seul son garbage collector peut venir à bout de ce problème. C'était une vraie necessité, je pense ne pas être le seul à m'être heurté à ce problème et PHP devient ainsi enfin un language utilisable dans un cadre beaucoup plus vaste que la simple création de pages web !
Vivement la version stable :)
Les commentaires récents