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:

  1. favicon.ico était manquant, qui mess avec mon trajet moteur. Bien que mon trajet moteur est très faible, mais en y favicon.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.
  2. Limite MaxRequestPerChild aide. Dans mon autre serveur dédié, j'ai mon MaxRequestPerChild 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ée MaxRequestPerChild aide à prévenir la fuite de mémoire par la création de nouveaux processus après limitée MaxRequestPerChild et l'ancien processus est en train de mourir. C'est mon nouveau réglage.

    ThreadsPerChild      1500
    MaxRequestsPerChild  10000 
  3. 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.

  4. 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.
  5. 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.
  6. 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).
  7. 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.