Pourquoi ce simple script php fuite de mémoire?
Dans l'espoir d'essayer d'éviter à l'avenir les fuites de mémoire dans les programmes de php (drupal modules, etc.) J'ai été déconner avec de simples scripts php de fuite de mémoire.
Pourrait php expert de m'aider à trouver ce que sur ce script provoque l'utilisation de la mémoire pour sans cesse monter?
Essayer de l'exécuter vous-même, de changer divers paramètres. Les résultats sont intéressants. Ici, il est:
<?php
function memstat() {
print "current memory usage: ". memory_get_usage() . "\n";
}
function waste_lots_of_memory($iters) {
$i = 0;
$object = new StdClass;
for (;$i < $iters; $i++) {
$object->{"member_" . $i} = array("blah blah blha" => 12345);
$object->{"membersonly_" . $i} = new StdClass;
$object->{"onlymember"} = array("blah blah blha" => 12345);
}
unset($object);
}
function waste_a_little_less_memory($iters) {
$i = 0;
$object = new StdClass;
for (;$i < $iters; $i++) {
$object->{"member_" . $i} = array("blah blah blha" => 12345);
$object->{"membersonly_" . $i} = new StdClass;
$object->{"onlymember"} = array("blah blah blha" => 12345);
unset($object->{"membersonly_". $i});
unset($object->{"member_" . $i});
unset($object->{"onlymember"});
}
unset($object);
}
memstat();
waste_a_little_less_memory(1000000);
memstat();
waste_lots_of_memory(10000);
memstat();
Pour moi, la sortie est:
current memory usage: 73308
current memory usage: 74996
current memory usage: 506676
[édité pour débloquer plus de membres de l'objet]
Je voudrais essayer de supprimer les lignes dans la boucle for à une heure, afin d'isoler le problème.
OriginalL'auteur mjgoins | 2009-07-17
Vous devez vous connecter pour publier un commentaire.
unset()
ne pas libérer la mémoire utilisée par une variable. La mémoire est libérée lorsque le "garbage collector" (entre guillemets parce que le PHP n'a pas un réel garbage collector avant la version 5.3.0, juste une mémoire libre routine qui a travaillé surtout sur les primitives), le juge approprié.Aussi, techniquement, vous ne devriez pas besoin d'appeler
unset()
depuis le$object
variable est limitée à la portée de votre fonction.Voici un script pour montrer la différence. J'ai modifié votre
memstat()
fonction pour afficher la mémoire différence depuis le dernier appel.Si vous utilisez des objets, assurez-vous que les classes implémentent
__unset()
afin de permettreunset()
pour bien clair ressources. Essayez d'éviter autant que possible l'utilisation de la variable de la structure des classes d'stdClass
ou de l'affectation de valeurs à des membres qui ne sont pas situés dans votre modèle de classe comme la mémoire assignée à ceux qui sont habituellement pas nettoyée correctement.PHP 5.3.0 et a une meilleure garbage collector, mais il est désactivé par défaut. Pour l'activer, vous devez appeler
gc_enable()
une fois.Donc la réponse est jusqu'à php 5.3, php pas exécuter arbitrairement long travail de mémoire fixe de l'espace. Même ma fonction que les fuites de moins de mémoire va tout doucement, mais avec une haute allocation de mémoire il faudrait plusieurs jours.
- Je exécuter plusieurs tâches qui peuvent prendre n'importe où à partir d'une minute à plusieurs heures. L'astuce consiste à éviter les objets (ou d'essayer de les réutiliser si vous devez) et le bâton avec les primitives (dans votre exemple, vous pouvez facilement utiliser des tableaux).
Si vous êtes à l'aide d'objets, assurez-vous que les classes implémentent __unset() pour annuler les ressources utilisées par la classe.
Moore: Êtes-vous en spéculant sur StdClass ou connaissez-vous quelque chose que je ne le fais pas? Les classes régulières peuvent également avoir des nouvelles, non déclarée, non membres affectés.
OriginalL'auteur Andrew Moore
memory_get_usage()
"Renvoie la quantité de mémoire, en octets, qui est actuellement alloué à votre script PHP."C'est la quantité de mémoire allouée au processus par le système d'exploitation, pas la quantité de mémoire utilisée par les variables assignées. PHP n'est pas toujours de libérer de la mémoire retour à l'OS -- mais que la mémoire peut encore être ré-utilisé lorsque de nouvelles variables sont allouées.
Cette démonstration est simple. Changer la fin de votre script:
Maintenant, si vous êtes correct, et PHP est en fait une fuite de mémoire, vous devriez voir mémoire de useage croître deux fois. Cependant, voici le résultat:
C'est parce que de mémoire "libéré" après la première invocation de waste_lots_of_memory() est utilisé par le deuxième appel.
Dans mes 5 ans avec PHP, j'ai écrit des scripts qui ont traité des millions d'objets et de gigaoctets de données sur une période de quelques heures, et les scripts qui ont couru pendant des mois à la fois. PHP de gestion de la mémoire n'est pas grand, mais il n'est pas aussi mauvais que vous le faites pour être.
OriginalL'auteur Frank Farmer
memory_get_usage
rapports de combien de mémoire php a alloué à partir de l'os. Il ne doit pas nécessairement correspondre à la taille de l'ensemble des variables en cours d'utilisation. Si php a un pic d'utilisation de la mémoire, il peut décider de ne pas retourner le montant non utilisé de la mémoire. Dans votre exemple, la fonctionwaste_a_little_less_memory
unsets les variables au fil du temps. Donc, l'utilisation de pointe est relativement faible. Lewaste_lots_of_memory
construit un grand nombre de variables (=beaucoup de mémoire utilisée) avant de le libérer. Donc, l'utilisation de pointe est beaucoup plus grande.OriginalL'auteur troelskn
Ma compréhension de la fonction memory_get_usage() est qu'elle est sortie dépend d'un large éventail de système d'exploitation et version facteurs.
Plus important encore, la suppression d'une variable n'a pas immédiatement le libre c'est de mémoire, le désallouer du processus, et de remettre le système d'exploitation (encore une fois, les caractéristiques de cette opération dépend du système d'exploitation).
En bref, vous avez probablement besoin d'une installation compliquée à regarder les fuites de mémoire.
OriginalL'auteur marr75
Je ne suis pas sûr quant à la nature exacte fonctionnement en PHP, mais dans quelques autres langues un objet contenant d'autres objets, lorsqu'elle est définie sur null, ce n'est pas, en soi, définissez les autres objets de valeur null. Il met fin à la référence à ces objets, mais que le PHP n'a pas de "garbage collection" en Java sens, les sous-objets existent dans la mémoire jusqu'à ce qu'ils sont supprimés individuellement.
unset()
etc réduire de comptage par un; si le nombre est réduit à zéro, la mémoire est libérée immédiatement dans la mémoire de PHP manager, prêt à être utilisé par une nouvelle variable.OriginalL'auteur Jason
fonction memory_get_usage() ne renvoie l'immédiat, l'utilisation de la mémoire, mais stockés en mémoire pour exécuter le processus.
DANS le cas d'un tableau énorme unset($array_a) ne libère pas la mémoire, mais qui consomment le plus, selon la fonction memory_get_usage() dans mon système...
l'écho de la fonction memory_get_usage();
OriginalL'auteur Miguel