3 votes

Demander à PHP de vider le tas en cas d'exception OutOfMemory

Je suis actuellement en train de déboguer un script qui rencontre constamment des exceptions OutOfMemory. Il est exécuté en tant que cronjob et fonctionne généralement bien, mais lorsque le cronjob n'a pas été exécuté pendant un certain temps (pour une raison quelconque), le script doit gérer trop d'éléments qui ont été mis en file d'attente et se heurte à une exception OutOfMemory.

En examinant le code, je n'ai pas été en mesure de repérer le problème. Je pense que l'un des appels de fonction itérative pourrait entraîner une fuite de mémoire, mais je ne suis pas sûr de savoir lequel et où. Existe-t-il une option permettant à PHP de vider le tas lorsqu'une exception OutOfMemory se produit ? Je pourrais peut-être identifier le problème à partir de là (très probablement).

5voto

Daniel Baulig Points 4849

Je n'ai pas trouvé d'option "dump heap on Exception", mais j'ai trouvé get_defined_vars() qui est en fait une vidange du tas si elle est appelée à partir d'un champ d'application global. En l'utilisant, j'ai pu voir qu'il y avait des centaines (en fait des milliers) de lignes de base de données encore référencées qui traînaient dans ma mémoire. Cela était dû à une ressource de résultat mysql non libérée quelque part dans la fameuse fonction qui causait la fuite. Je l'ai trouvée et corrigée. Le système fonctionne bien maintenant.

1voto

Thariama Points 26420

L'approche la plus simple serait d'utiliser un bloc try-catch autour de la partie de votre script où l'erreur peut se produire et vous devrez vider la pile dans la partie catch. Le problème pourrait être que la machine ne sera pas en mesure de réagir parce que la mémoire est pleine et qu'elle se termine. Je ne sais pas s'il est utile de supprimer certaines variables pour libérer de la mémoire afin de produire des données.

EDIT : Pour ce faire, utilisez la fonction php debug-backtrace . Vous obtiendrez ainsi une trace de la pile. Ainsi, il sera plus facile de trouver l'erreur si la machine est toujours en service.

0voto

joni Points 2885

Ne chargez pas tous les objets ensemble dans la mémoire, mais lisez-les au fur et à mesure que vous les traitez ?

0voto

Quamis Points 4301

J'ai eu beaucoup de problèmes avec simpleXML et des fuites de mémoire. Il m'a fallu des jours pour comprendre que simpleXML était à l'origine de ces fuites et pour les corriger. Pour autant que je sache, il est possible de programmer une manipulation pour OOM :)

De plus, les fonctions de PHP pour afficher les informations de mémoire ne détectent pas les fuites de mémoire, j'avais des scripts qui consommaient ~1Gb de ram, mais les fonctions de PHP n'indiquaient que 100Mb utilisés :)

0voto

Josh from Qaribou Points 955

C'est le meilleur "heap dump" que j'ai pu écrire rapidement en PHP. Je prends les variables et les fonctions définies, puis je les trie selon leur longueur sérialisée. La longueur sérialisée n'est pas une méthode fiable à 100% pour obtenir la taille d'une variable, mais elle est assez bonne, et généralement utile pour déterminer quels objets sont les plus gourmands en mémoire :

$memmap = array_map(function($var) { return strlen(serialize($var)); }, array_merge(get_defined_functions(), get_defined_vars())); arsort($memmap); var_dump($memmap);

Vous pouvez modifier légèrement la fonction de rappel si vous souhaitez que les résultats soient plus détaillés ou qu'ils parcourent les variables définies.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X