Fatal error: Out of memory, mais j'ai beaucoup de mémoire (PHP)
Depuis ma question est de plus en plus longues et de plus, je décide de ré-écrire toute la question pour l'améliorer et le rendre plus court.
Je lance mon site internet sur serveur dédié avec 8 go de mémoire. Je suis pleinement conscient que je dois augmenter la limite de mémoire php.paramètre ini. J'ai mis de 128M de 256M et à -1. Toujours le problème de la persistance.
Fatal error: Out of memory (alloués 786432) (tried to allocate 24576
octets) D:\www\football\views\main.php sur la ligne 81
La mémoire n'a pas de sens car il dit seulement 786432 octets est alloué et il fallait 24576 octets de plus.
786432 octets est seulement 768 kilo-octets et est assez petit.
Conseils
- L'erreur se produit sur une ligne aléatoire. Il n'est pas toujours l'erreur sur la ligne numéro 81.
- À l'heure de pointe, Apache prend seulement environ 500 mo de mémoire. J'ai encore 6 GO de rechange.
- Il n'y a pas de boucle infinie.
- Le script prend 1,042,424 octets. L'obtention de ce numéro de
echo memory_get_peak_usage();
- Le jeu de résultats de MySQL est faible (au plus 12 de lignes, purement texte, pas de données blob)
- (Important) Si je redémarre Apache une fois tous les deux jours, l'erreur a disparu. Il se produit généralement lors de l'exécution d'Apache plus de 2 jours.
- J'ai inclus le profilage le script et vous pouvez l'obtenir ici.
- Ce serveur dédié est purement utilisée pour exécuter un seul site web. Ce site est un haut trafic de site web avec une moyenne de 1000 visiteurs chaque minute. À l'heure de pointe, il y aura de 1 700 à 2 000 visiteurs d'accéder en même temps.
Serveur Spec
Système d'exploitation: Windows 2008 R2 64 Bits
PROCESSEUR: Intel Core i5 - 4 cœurs
RAM: 8 GO
Apache 2.2
PHP 5.3.1
Stockage: 2 x 1 to disques durs
Bande passante: 10 to par mois
Solution
J'ai enfin réglé et résolu le problème et je tiens à partager ici ce que j'ai fait pour l'améliorer:
favicon.ico
était manquant, qui mess avec mon trajet moteur. Bien que mon trajet moteur est très faible, mais en yfavicon.ico
, elle permet de réduire l'utilisation de la mémoire en n'exécutant pas de route à moteur. La plupart de la partie de mon site web a, et j'ai oublié de le mettre pour cette nouvelle section.-
Limite
MaxRequestPerChild
aide. Dans mon autre serveur dédié, j'ai monMaxRequestPerChild
limitée. Pour ce serveur, je l'ai mis à 0. J'ai toujours pensé que chaque script est isolé. Disons que si mon script prend 800ko à exécuter. Dès son achèvement, Apache ou de PHP doit gratuit de 800 ko de mémoire. Il semble qu'il ne fonctionne pas de cette façon. LimitéeMaxRequestPerChild
aide à prévenir la fuite de mémoire par la création de nouveaux processus après limitéeMaxRequestPerChild
et l'ancien processus est en train de mourir. C'est mon nouveau réglage.ThreadsPerChild 1500 MaxRequestsPerChild 10000
-
ob_flush();
fait de réduire un peu plus de mémoire. Il n'aide pas beaucoup, mais tous les bits de l'optimisation de l'aide. - J'ai utilisé
xdebug
que je n'ai jamais utilisé avant comme suggéré par des gens qui tentent de répondre à cette question. Je dois dire que c'est l'outil idéal et j'ai optimisé un peu fourre pour le faire courir un peu plus vite. - J'ai désactiver un peu inutile module Apache. Je suis en train de le désactiver un par un et de le laisser quelques jours de test pour s'assurer qu'il fonctionne parfaitement avant que je désactiver un autre. J'ai tous inutiles extension PHP désactiver maintenant.
- La plupart de mon script dans ce serveur utilisé de façon traditionnelle (pas de modèle, pas de couche de base de données, pur PHP, HTML, et l'héritage mysql_* fonction). Pour être honnête, il est très rapide et extrêmement petite mémoire. Toutefois, l'entretien, le script n'est pas très facile car le site est de plus en plus longues. J'ai essayé de convertir certaines parties du site dans un cadre approprié (mon petit cadre). La raison que j'ai utilisé mon propre cadre de référence, car il est tout petit (3 ko pour l'ensemble du cadre et ne comprennent que ce dont j'ai besoin).
- De commutation de IIS7.5 la résolution de ce problème complètement.
- Je sent boucle infinie. 🙂 Quelle version de PHP? Et comment combat que le code sur la ligne 81.
- Il n'y a pas de boucle infinie, car 70% du temps, le script fonctionne, et autour de 30% du temps, il dit qu'il manque de mémoire. Je triple-vérifier le code. Encore une chose, c'est que j'ai vérifier l'utilisation de la mémoire du script avec memory_get_peak_usage(). Il consomme seulement 800 ko par le script.
- Code de l'aide.
- Certainement, méritent une upvote Leigh /\
- Juste parce qu'il travaille à 70% du temps ne veut pas dire que certains variable d'entrée ou de ne pas faire le train venir des pistes et de tuer les villageois. Je suis assez positive que le train est une boucle infinie. 😀
- 32bits ou 64 bits du système?
- Ce type est
$value
? (Ou plutôt, d'où vient-elle?) - Pouvez-vous faire un
free -m
sur le serveur lui-même et de vérifier que vous avez effectivement 800k de libérer de la mémoire à allouer. - Quand vous dites, "il fonctionne parfaitement bien avec le serveur local", avez-vous touché que le serveur local avec, disons, 1 millions de pages vues? (Vous avez compris que le numéro de votre de 200 000 vues/jour * 5 jours. Donc, pas tout à fait de l'air mince.)
- bonne question. Je n'ai pas testé avec 1 000 000 de pages vues avec le serveur local. Ce que je ne comprends pas c'est que Apache utilisé uniquement autour de 400 mo. Il y a environ 6 go de mémoire et le message d'erreur dit que je n'ai pas 24576 octets supplémentaires de mémoire à allouer. Mon memory_limit est de -1 qui, je crois, il n'y a pas de restriction.
- Je me souviens avoir eu un problème similaire, c'est parce que j'ai utilisé une boucle pour insérer des données dans la base de données à l'aide de la doctrine, et pour chaque itération, il a ouvert un curseur dans la base de données !
- D'une part, si vous pouvez reproduire le problème localement, il est beaucoup plus facile à résoudre. D'autre part, il peut être difficile de reproduire fidèlement l'environnement d'exécution, même lorsque vous commencez avec un serveur dédié. (Le matériel est susceptible d'entrer en jeu).
- Réfléchissons un peu out-of-the-box. Avez-vous une limite de mémoire sur les processus apache? Pourrait-il y avoir
ulimit
en effet (peut-être pour le web de l'utilisateur ou du propriétaire du script PHP, par exemple dans .de profil)? Avez-vous essayé de lancer le script en CLI dès qu'il cesse de fonctionner le module Apache? Utilisez-vous un quelconque mécanisme de mise en cache modules PHP? Utilisez-vous suhosin ou similaire durcissement des modules? - Le problème est que l'erreur a semblé tellement aléatoire que je ne peut pas réduire la cause. Ne redémarrez le serveur une fois tous les 2 jours, on peut s'assurer que le problème ne se produira jamais. En heure de pointe, il y aura environ 1 700 utilisateurs de connexion en même temps. Peut-il être un problème?
- Il n'y a pas de
ulimit
dans ma Configuration d'Apache. Ce serveur dédié est dédié à exécuter seulement ce site seul avec aucun autre site. Je n'ai pas de mécanisme de cache. J'ai seulement utiliser memcached pour toute requête cher que, souvent appelé. (J'ai mis à jour la liste de l'extension dans mon post. Vous pouvez vérifier.) - Quel est le résultat de cette requête mysql:
EXPLAIN your_query_here
? - si vous allez sur mon lien de serveur, vous seriez probablement voir ce que le retour du résultat. Il retourne le nom des 2 équipes, leur logo, le chemin de l'image, et de leurs objectifs. Le résultat sera regroupés par date en PHP. (Je sais que cette question est très mal de tête et une longue +1 à chaque commentaire comme une récompense pour payer l'attention sur cette question)
- Ce n'est pas ce que je demande. Je ne veux pas voir les données renvoyées par la requête. Je demande le résultat de
EXPLAIN your_query_here
. Seulement quelqu'un avec un accès direct à votre serveur mysql peut le savoir. - J'ai mis à jour ce que vous avez demandé sur mon post. Vous pouvez vérifier.
- Il faudrait vraiment aider si vous pouviez partager le code jusqu'à, disons, la ligne 85.
- J'ai mis à jour plus de code jusqu'à la ligne 86. De toute façon, l'erreur est très aléatoire. Parfois, les erreurs sur les différentes lignes.
- jusqu'à 85, je veux dire de 1 à 85. Le 7 lignes vous avez posté le dire très peu. Je ne peux pas voir si c'est dans une boucle, si elle est exécutée de manière conditionnelle, ce qui se passe avant, etc. Comme vous pouvez le voir ce n'est pas une simple question, donc plus vous laissez-nous savoir le mieux.
- Ce qui est Apache ThreadsPerChild valeur?
- Merci de poster plus de votre code. Il serait également intéressant de données dans vos tables. Si le redémarrage du serveur contribue que pour un temps, il pourrait être une fuite de mémoire, certes, mais il n'a pas besoin d'être PHPs faute. Vous êtes peut-être l'ajout d'un grand nombre de données pour les sessions de vos utilisateurs? Cela pourrait expliquer pourquoi cela fonctionne localement, il n'existe tout simplement pas que de nombreux / si tous les utilisateurs.
- Il est peu probable que la ligne de l'erreur mentionne que soit la cause réelle du problème, il sera juste le bout de code qui a poussé trop loin (donc pourquoi ça change). Les choses que je voudrais être à la recherche pour le avant la ligne 81 aurait $_SESSION demandes, la génération d'images, compliqué ou intelligente des fichiers systèmes... Ou il pourrait être quelque chose d'autre enitrely plus basé sur un serveur. Une chose à vérifier serait que votre db connexions sont fermées après vous avez terminé avec eux, en particulier sur un highload site, vous pouvez même essayer de connexions persistantes. Ce type de table est de votre table db?
- Je dirais aussi qu'en dernier recours, fuir les plates-formes Windows, et de migrer vers le même Linux (debian serveur) - ce qui, en soi, pourrait résoudre les fuites de mémoire (nous savons tous que Windows vaut la peine). Aussi, EXPLIQUER votre post n'est pas les résultats de l'EXPLIQUER. Exécuter EXPLIQUER, ANALYSER et publier les résultats - il NE doit comporter aucun résultat normal des données dans la réponse.
Vous devez vous connecter pour publier un commentaire.
Je suis tombé sur le même genre de problème avec le serveur de mourir lors de l'utilisation de la swap. C'est parce que mod_php ne libère pas la mémoire jamais. Donc, processus Apache continuer de croître, soit en arrivant à apache ou de PHP limite de mémoire ou, si il n'y a pas de limite, le plantage du serveur.
Le redémarrage d'apache rend pour frayer de nouvelles fraîches slim processus, mais l'exécution des scripts PHP au fil du temps, ils grandissent jusqu'à ce que les problèmes surviennent.
La solution est de faire de apache tuer les processus après un certain nombre de requêtes servies donc, il va en créer de nouvelles ( Il y a quelques questions à ce sujet) la réduction de la MaxRequestsPerChild option de configuration, disons, 100 (valeur par Défaut: 1000).
Bien sûr, cela peut réduire le serveur de performances car il faut des ressources pour les tuer et de frayer de nouveaux processus, mais au moins il garde le site de travail. Vous pourriez être tenté d'augmenter le nombre de processus en cours d'exécution pour garder des performances de haut, assurez-vous (PHP ou apache) limite de mémoire max x nombre de procédés de ne pas obtenir plus de votre serveur de ram physique.
Voici mon expérience, j'espère que ça aide.
Pour commencer,
memory_get_peak_usage()
ne sera pas utile ici. Il retournera seulement la quantité de mémoire qui a été allouée, et c'est le même numéro qui a provoqué l'erreur.memory_get_usage
sera de retour l'actif de la quantité de mémoire qui est allouée lorsqu'il est appelé.ini_set('memory_limit', '256M');
va définir l'allocation maximale de PHP empreinte sur vos systèmes de Mémoire. Si vous obtenez OOM à 768K, upping il ne résoudra pas le problème.Il n'y a aucune indication quant à ce que la version de PHP que vous utilisez, mais je voudrais suggérer une mise à jour immédiatement. Il y a plusieurs bugs où Zend Gestionnaire de Mémoire ne désalloue la mémoire, ce qui vous ferait exactement le même problème.
Sont à la fois votre serveur local et le serveur de production exécuter la même version de système d'exploitation, la même longueur de bits et la même version de PHP? La réponse sera "non".
Si elle n'est pas liée à la windows
malloc()
problème, c'est un sous domaine et probablement dans un VirtualHost, et en allouant seulement 768k, on dirait presque un OS question.Exécuter
tasklist
à partir de l'invite de commande lorsque vous accédez à votre script. Voyez-vous un supplément de Apache thread, ou de l'utilisation de la Mémoire à travers le processus de spike?Une dernière idée est, exécutez
flush()
et/ouob_flush();
après chaque tour de boucle pour la table de la ligne/colonne. Ceci devrait effacer de votre mémoire tampon et vous faire économiser un peu de mémoire dans l'événement c'est là que le problème se produit.Je voudrais commencer par la mise à niveau de PHP 5.4+ que c'est jusqu'à 50% plus rapide pour certaines applications.
Ils ont fixé un grand nombre de fuites de mémoire. Veuillez voir becnhamrks: http://news.php.net/php.internals/57760
Installer xdebug et activer le générateur de profils de déclenchement.
Générer un fichier de générateur de profils, puis après le cachegrind fichier si vous ne serait pas encore en mesure de déterminer la source du problème.
EDIT: profiler fichier de la page où la fuite de mémoire se produit bien sûr!
Veuillez noter que l'erreur est
Out of memory
et n'est pasAllowed memory size [..] exhausted
.Donc la fuite de mémoire est d'ailleurs sur le système. Il est possible que le serveur mysql utilise beaucoup de mémoire système après cette lourde requête, laissant apache/php sans qu'il soit physique et swap.
Ce qui peut expliquer l'erreur toujours sur la même ligne (et/ou dans le même script).
Je suppose que vous n'avez pas modifié le droit
php.ini
ou que vous n'avez pas redémarré PHP et/ou le serveur web.Créer un
phpinfo.php
page dans votre docroot avec le contenu<?php phpinfo();
afin de vous assurer de changer la bonnephp.ini
. En plus de l'emplacement de laphp.ini
fichier que le serveur web utilise, il sera également le maximum de mémoire de script permis.Ensuite, je voudrais ajouter quelques traces de pile à votre page de sorte que vous pouvez voir la chaîne des événements qui ont conduit à cela. La fonction suivante va attraper les erreurs fatales et de fournir plus d'informations sur ce qui s'est passé.
Personnellement, Nginx + PHP-FPM est ce que j'ai utilisé pendant des années depuis que j'ai quitté lent ol' Apache.
php.ini
?Pourrait être un problème avec MySQL et le nombre de connexions ouvertes, donc pourquoi il résout de lui-même lorsque vous redémarrez tous les quelques jours. Sont-ils auto fermeture sur le script d'arrêt?
memcached
.Hey j'ai aussi eu le même problème sur mon serveur. Je viens de changer les choses suivantes :
changement
php.ini
à...et ajouter à
httpd.conf
et redémarrer apache & j'ai supprimé le message d'erreur :
Juste pour rappel (je suis en ajoutant cette réponse très loin de la question initiale):
Si elles sont toutes valables, alors la seule explication possible est que les 6 go est très fragmenté qui je pense est un peu improbable. Vous n'avez pas dit comment PHP est appelé à partir d'Apache - mod_php? fpm? Fcgi?
Je voudrais commencer par l'examen de chacun de ces prédicats - en particulier la mémoire libre un. Comment savez-vous qu'il y a 6 go de libre lorsque l'erreur se produit? Une cause plus probable est qu'il y a une fuite de mémoire se produisant laquelle vous n'êtes pas de taches.
Vous n'avez pas fourni tous les détails de la manière dont apache est configuré; j'aimerais aussi avoir un coup d'oeil à la réduction de MaxRequestsPerChild et MaxMemFree. (Je ne suis pas très familier avec un travailleur de apache où cela s'applique par thread - vraiment vous avez besoin d'une limite par processus). Si vous avez fourni la base réglage de la config d'apache, alors peut-être que nous pourrions faire d'autres suggestions.
Sauf si vous utilisez Ajax largement, assurez-vous que votre keepalive temps est de 2 ou moins.
Fatal error: Out of memory (alloués RÉSOLU
j'ai eu le même problème, depuis des mois, aucune solution. enfin j'ai été vérifier dans l'un de apache dossiers, je.e(\apache\conf\extra) je suis tombé sur ce fichier qui contrôle l'allocation de mémoire de apache. le nom de fichier est httpd-mpm dans ce fichier, vous augmentez la MaxMemFree qui est mis en 2048 de quelque chose de plus, j'ai pris le mien à 10 000 pour la première MaxMemFree (IfModule !mpm_netware_module) puis faites la seconde MaxMemFree à 5000 IfModule mpm_netware_module.
Ces résolu mon problème. espérons que cela aide
Les deux éléments suivants certainement point à des fuites de mémoire:
Je serait le premier single sorti AOP, la désactivation de tous les autres extensions et laisser tourner toute la nuit en utilisant quelque chose comme Siège /Apache Bench (ab). Vous pouvez aussi essayer de l'exécuter à l'aide de la
cli
interface (assurez-vous de garder les mêmes limites de la mémoire).Vous pouvez utiliser le
memory_get_peak_usage()
fonction à la fin de votre script pour afficher la quantité de mémoire PHP il pense qu'il a été à l'aide.De votre commentaire c'est 800 ko, ce qui est correct; certainement pas la gigantesque quantité de mémoire qui serait la cause d'un mémoire 😉
Enfin, bien que je ne recommande pas la mise à niveau de 5.4 à ce stade, la mise à niveau vers la dernière 5.3.x vaut probablement en raison de multiples vulnérabilités et les fuites qui ont été réglés depuis 5.3.1
memory_get_peak_usauge()
et il a utilisé autour de 800 ko à chaque fois. J'ai modifié les différentes configurations et je mettrai à jour ce que j'ai observé plus tard.ce qui m'est arrivé il y a quelques jours. J'ai fait une nouvelle installation et toujours il s'est passé. autant que tout le monde voit et basé sur les spécifications de votre serveur. le plus probable, c'est une boucle infinie. il pourrait ne pas être sur le code PHP lui-même, mais sur les demandes faites auprès de Apache.
permet de dire que lorsque vous accéder à cette url http://localhost/mysite/page_with_multiple_requests
Vérifier votre Apache, journal d'accès s'il reçoit plusieurs demandes. la trace de la demande et vérifier le code qui pourrait provoquer un goulot d'étranglement pour le système (le mien exec() lors de l'utilisation de sendmail). Le goulot d'étranglement je vous parle n'a pas besoin d'être un "infinite loop". Il pourrait être une fonction qui prend quand même le temps de terminer. ou peut-être que certains de php 'programme d'exécution des fonctions'
Vous pourriez avoir besoin de vérifier les requêtes ajax trop (ceux qui s'exécutent quand le chargement de la page). si cette requête ajax redirige vers la même url
par exemple httpx://localhost/monsite/page_with_multiple_requests
il serait "rétablir" la demande de tout recommencer
il serait utile si vous poster les lignes au hasard ou le code lui-même lorsque le script se termine peut-être qu'il est un "loop" code quelque part par là. à mon humble avis, php ne sera pas seulement d'appel aléatoire de lignes pour rien.
http://blog.piratelufi.com/2012/08/browser-sending-multiple-requests-at-once/
La plupart du temps vous obtenez une telle erreur, problème est dans le code. Je ne suis pas en train de dire que vous écrivez du code qui est mauvais, je suis en train de dire que vous devez observer attentivement ce qu'il y a en utilisant cette quantité de quantité de mémoire.
Rappelez-vous toujours "de collecte des Ordures en PHP est assez mauvais", c'est pas comme en Java, toute autre langue. il y a un moyen d'assurer la collecte des ordures à travers gc_collect_cycle, mais, dans mon opinion personnelle, qui ne permettent pas de résoudre votre problème.
PHP gratuit toute la mémoire utilisée pour l'exécution d'une page, une fois de requête-réponse, le cycle est complet, vous risquez de rencontrer des problèmes de mémoire, si votre script est en cours d'exécution longue, comme une toile de fond de script(Gearman etc), parce que, de mémoire n'est pas libérés jusqu'à ce que le script est en cours d'exécution.
Si ci-dessus n'est pas le cas avec votre scr,pt, et comme vous l'avez dit il n'y a pas de code qui nécessite une grande quantité de mémoire, puis le problème est très certainement dans le code lui-même, et la mise à niveau de toute version de PHP ne résoudra pas le problème. J'ai été confronté à l'un de mes Gearman scripts une fois, et il y avait un problème avec un de mes boucle où j'étais en ajoutant une variable à l'un de mes tableau, la variable elle-même était très lourd (environ 110KB de données). Donc, je dirais, faire une inspection minutieuse de votre code.
Ravir
J'ai eu un problème similaire avec PHP:
1) Vérifiez vos journaux d'erreur. Éliminer TOUTES les erreurs avant de continuer.
2) Envisager la possibilité de modifier votre configuration d'apache pour éliminer les modules inutilisés - cela permettra de réduire l'empreinte nécessaire par le PHP, voici un excellent lien pour cela - il est spécifique à WordPress, mais devrait encore être très utile http://thethemefoundry.com/blog/optimize-apache-wordpress/
Pour vous donner une idée du genre de bug que j'ai trouvé, j'ai eu un peu de code qui essayait de publier du contenu sur Facebook, Facebook a ensuite modifié leur API, donc, ce qui a rompu, j'ai aussi utilisé un contenu expirator' ce qui en gros veut dire qu'il a gardé de la nouvelle tentative de publier ce contenu sur Facebook et en laissant des charges des objets se trouvant dans la mémoire.
Par le profileur de fichier de sortie, j'ai remarqué un couple de choses que je n'aime pas/beaucoup de confiance et il va examiner ces:
Outre de ne pas connaître le sens de la sortie des numéros de détecter une anomalie ou comment les scripts PHP de travail..., n'Est-ce pas un problème? Avoir un include de la même main.ph fichier, qui ressemble à un appel récursif chose?
Remarqué le fichier
D:\www\football\views\main.php
est prise de l'utilisation de certaines fonctions de chaîne plusieurs fois, je suppose que c'est l'appel de ces fonctions sur les données renvoyées par la requête:Si, comme dans le langage C, ces fonctions nécessitent des chaînes
null
de cessation ou de quelque autre fin de fin de chaîne pour éviter les problèmes de mémoire, je regarde les chaînes renvoyées par la requête.Pouvez-vous poster l'url de votre site web?
views\main.php
est inclus qu'une seule fois.C'est un bogue connu dans PHP v 5.2 pour Windows, il est présent au moins à la version 5.2.3: https://bugs.php.net/bug.php?id=41615
Aucun des corrections suggérées ont aidé pour nous, nous allons avoir à mettre à jour PHP.
Essayez d'exécuter php sur fcgid, cela peut vous aider:
Source: Apache 2.4.6.0 crash dû à un problème dans php5ts.dll 5.5.1.0
Je dirais que le serveur est en cours d'exécution hors de la physique/la mémoire de swap, donc PHP ne peut pas allouer suffisamment de mémoire.
Pouvez-vous coller la sortie de
free
ici?Pour mon cas, cette erreur a été déclenchée à cause d'une énorme requête select (des centaines de milliers de résultats retournés).
Il se leva immédiatement après l'ajout de millions d'enregistrements dans ma Base de données pour tester l'évolutivité de WordPress, donc c'était la seule raison probable pour moi.