Comme ma question est de plus en plus longue, je décide de réécrire toute la question pour la rendre meilleure et plus courte.
Je dirige mon site Web sur un serveur dédié avec 8 Go de mémoire. Je suis tout à fait conscient que je dois augmenter la limite de mémoire sur le paramètre php.ini. Je l'ai réglé de 128M à 256M et à -1. Le problème reste la persistance.
Erreur fatale: Mémoire insuffisante (786432 affecté) (tentative d'allocation de 24576 Octets) dans D:\www\football\views\main.php à la ligne 81
Le manque de mémoire n'a pas de sens car il est dit que seuls 786432 octets sont alloués et qu'il en faut plus de 24576 octets.
786432 octets ne font que 768 kilo-octets et sont assez petits.
echo memory_get_peak_usage();
Système d'exploitation: Windows 2008 R2 64 bits
CPU: Intel Core i5 - 4 cœurs
RAM: 8 Go
Apache 2.2
PHP 5.3.1
Stockage: 2 x 1 TB disques durs
Bande passante: 10 TB par mois
J'ai enfin réglé et corrigé le problème et je voudrais partager ici ce que j'ai fait pour l'améliorer:
favicon.ico
manquait quel gâchis avec mon moteur de route. Bien que mon moteur de routage soit très petit, mais en incluant favicon.ico
, il permet de réduire l'utilisation de la mémoire en n'exécutant pas mon moteur de routage. La majeure partie de mon site l’a et j’ai oublié de le mettre pour cette nouvelle section.Limiter MaxRequestPerChild
aide. Sur mon autre serveur dédié, ma MaxRequestPerChild
est limitée. Pour ce serveur, je l'ai mis à 0. J'ai toujours pensé que chaque script était isolé. Disons que si mon script prend 800 Ko à exécuter. Une fois terminé, Apache ou PHP devrait libérer 800 Ko de mémoire. Il semble que cela ne fonctionne pas de cette façon. Limited MaxRequestPerChild
aide à prévenir les fuites de mémoire en créant un nouveau processus après MaxRequestPerChild
limité et que l'ancien processus est en train de mourir. Ceci est mon nouveau paramètre.
ThreadsPerChild 1500
MaxRequestsPerChild 10000
ob_flush();
réduit légèrement plus la mémoire. Cela n’aide pas beaucoup mais chaque optimisation est utile.
xdebug
que je n'ai jamais utilisé auparavant, comme suggéré par des personnes qui tentent de répondre à cette question. Je dois dire que c’est un excellent outil et j’ai optimisé quelques éléments pour le rendre légèrement plus rapide.J'ai rencontré le même genre de problème avec le serveur en train de mourir en essayant d'utiliser le swap. En effet, mod_php ne libère jamais la mémoire. Ainsi, les processus Apache ne cessent de croître, atteignant soit la limite de mémoire d'Apache ou de PHP, soit, s'il n'y en a pas, un crash du serveur.
Le redémarrage d'Apache permet de créer de nouveaux processus minces, mais à mesure qu'ils exécutent des scripts PHP au fil du temps, ils se développent jusqu'à ce que des problèmes se posent.
La solution consiste à obliger Apache à supprimer les processus après un certain nombre de requêtes afin qu’il en crée de nouvelles (il y a quelques questions liées à cela ) réduisant l’option MaxRequestsPerChild configuration à, disons 100 ( La valeur par défaut est 1000).
Bien sûr, cela peut réduire les performances du serveur car il faut des ressources pour tuer et générer de nouveaux processus, mais au moins, le site continue de fonctionner. Vous pourriez être tenté d'augmenter le nombre de processus en cours pour maintenir des performances élevées. Assurez-vous que la limite de mémoire PHP (ou Apache) x nombre maximal de processus ne dépasse pas la mémoire physique de votre serveur.
Voici mon expérience, espérons que cela aide.
Pour commencer, memory_get_peak_usage()
ne sera pas utile ici. Il ne retournera que la quantité de mémoire allouée, et c'est le même nombre qui a causé l'erreur.
memory_get_usage
renverra la quantité de mémoire active allouée lors de son appel.
ini_set('memory_limit', '256M');
définira l’allocation maximale de l’empreinte PHP sur la mémoire de votre système. Si vous obtenez le MOO à 768K, le fait d’augmenter ne résoudra pas le problème.
Il n'y a aucune indication sur la version de PHP que vous utilisez, mais je suggérerais une mise à niveau immédiatement. Il y a plusieurs bogues où le gestionnaire de mémoire de Zend ne parvient pas à libérer de la mémoire, ce qui vous mènerait exactement au même problème.
Votre serveur local et votre serveur de production utilisent-ils la même version du système d'exploitation, le même bit long et la même version de PHP? La réponse sera non.
S'il n'est pas lié au problème windows malloc()
, étant un sous-domaine et probablement au sein d'un VirtualHost et n'attribuant que 768 Ko, cela ressemble presque à un problème de système d'exploitation.
Exécutez tasklist
à partir de la commande Invite lorsque vous accédez à votre script. Voyez-vous un thread Apache supplémentaire ou une utilisation de la mémoire au cours de la hausse des processus?
Une dernière idée est, exécutez flush()
et/ou ob_flush();
après chaque boucle pour la ligne/colonne du tableau. Cela devrait effacer votre mémoire tampon et vous faire économiser de la mémoire au cas où le problème se produirait.
Je commencerais par mettre à niveau PHP vers la version 5.4+, car certaines applications sont jusqu'à 50% plus rapides . Ils ont corrigé un grand nombre de fuites de mémoire. Veuillez voir becnhamrks: http://news.php.net/php.internals/57760
Installez xdebug et activez le déclencheur du profileur . Générez un fichier de profileur, puis publiez le fichier cachegrind si vous ne pouvez toujours pas identifier la source du problème.
EDIT: fichier de profileur 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 pas Allowed memory size [..] exhausted
.
Donc, la fuite de mémoire est ailleurs sur le système. Il est possible que le serveur mysql utilise beaucoup de mémoire système après cette requête lourde, laissant Apache/php sans lui et sans swap physique.
Cela devrait expliquer l'erreur toujours sur la même ligne (et/ou dans le même script).
Je suppose que vous n’avez pas édité le bon php.ini
ou n’avez pas redémarré PHP et/ou le serveur Web.
Créez une page phpinfo.php
dans votre docroot avec le contenu <?php phpinfo();
pour vous assurer que vous modifiez le php.ini
correct. Outre l'emplacement du fichier php.ini
utilisé par le serveur Web, il indique également la mémoire de script maximale autorisée.
Ensuite, j'ajouterais quelques traces de pile à votre page afin que vous puissiez voir la chaîne d'événements qui ont conduit à cela. La fonction suivante détectera les erreurs fatales et fournira plus d'informations sur ce qui s'est passé.
register_shutdown_function(function()
{
if($error = error_get_last())
{
// Should actually log this instead of printing out...
var_dump($error);
var_dump(debug_backtrace());
}
});
Personnellement, Nginx + PHP-FPM est ce que j’ai utilisé pendant des années, depuis que j’ai quitté le lent Apache.
Hey, j'ai aussi le même problème sur mon serveur. Je viens de changer les choses suivantes:
remplacez php.ini
par ...
memory_limit = 128M
et ajouter à httpd.conf
RLimitMEM 1073741824 2147483648
et redémarrez Apache et j'ai supprimé l'erreur:
Peut-être un problème avec MySQL et le nombre de connexions ouvertes, d’où sa résolution lors du redémarrage tous les quelques jours. Est-ce qu'ils se ferment automatiquement à la fermeture du script?
Juste pour récapituler (j'ajoute cette réponse assez loin de la question initiale):
Si tout cela est valable, alors la seule explication possible est que le 6Gb est très fragmenté - ce qui me semble un peu improbable. Vous n'avez pas dit comment PHP est appelé depuis Apache - mod_php? fpm? Fcgi?
Je commencerais par examiner chacun des prédicats ci-dessus, en particulier celui de la mémoire libre. Comment savez-vous qu'il y a 6 Go libre lorsque l'erreur se produit ? Une cause plus probable est qu'il se produit une fuite de mémoire que vous ne détectez pas.
Vous n'avez fourni aucun détail sur la configuration d'Apache. Je voudrais aussi voir comment réduire MaxRequestsPerChild et MaxMemFree. (Je ne connais pas très bien Apache, où cela s'appliquera par thread - vous avez vraiment besoin d'une limite par processus). Si vous fournissiez le paramètre de base de la configuration Apache, nous pourrions peut-être faire d'autres suggestions.
Sauf si vous utilisez abondamment Ajax, assurez-vous que votre durée de conservation est de 2 ou moins.
cela m'est arrivé il y a quelques jours. J'ai fait une nouvelle installation et c'est toujours arrivé. autant que tout le monde voit et basé sur les spécifications de votre serveur. le plus probable est une boucle infinie. il pourrait ne pas s'agir du code PHP lui-même, mais des requêtes adressées à Apache.
disons que lorsque vous accédez à cette URL http: // localhost/mysite/page_with_multiple_requests
Consultez le journal des accès de votre Apache s'il reçoit plusieurs demandes. retracez cette demande et extrayez le code qui pourrait causer un «goulot d'étranglement» au système (exec () lorsque j'utilise sendmail). Le goulot d'étranglement dont je parle n'a pas besoin d'être une "boucle infinie". Ce pourrait être une fonction qui prend un certain temps à terminer. ou peut-être quelques unes des ' fonctions d'exécution du programme ' de php
Vous devrez peut-être aussi vérifier les requêtes ajax (celles qui sont exécutées lors du chargement de la page). si cette demande ajax redirige vers la même URL
par exemple. httpx: // localhost/mysite/page_with_multiple_requests
il serait 'refaire' les demandes encore une fois
cela aiderait si vous postez les lignes aléatoires ou le code lui-même où le script se termine, peut-être y at-il un code "en boucle" quelque part. imho php n'appelle pas que des lignes aléatoires pour rien.
http://blog.piratelufi.com/2012/08/browser-sending-multiple-requests-at-once/
J'ai eu un problème similaire avec PHP:
1) Vérifiez vos journaux d'erreur. Éliminez TOUTES les erreurs avant de continuer . 2) Envisagez de modifier votre configuration Apache pour éliminer les modules inutilisés - ceci réduira l'empreinte nécessaire à PHP - voici un excellent lien pour cela - il est spécifique à Wordpress mais devrait être très utile http://thethemefoundry.com/blog/optimize-Apache-wordpress/
Pour vous donner une idée du type de bogue que j'ai trouvé, j'avais un code qui essayait de poster du contenu sur Facebook, Facebook a ensuite modifié leur API, donc ça a cassé, j'ai aussi utilisé un 'expirateur de contenu', ce qui signifiait essentiellement qu'il réessayait. pour publier ce contenu sur Facebook en laissant des charges d'objets en mémoire.
Essayez d’exécuter php sur fcgid, cela peut aider:
Ce sont les erreurs classiques que vous verrez lors de l’exécution de PHP en tant que Module Apache. Nous avons lutté avec ces erreurs pendant des mois. Passer à utiliser PHP via mod_fcgid (comme le recommande James) résoudra tous ces problèmes problèmes. Assurez-vous de disposer de la dernière version redistribuable de Visual C++ paquet installé:
http://support.Microsoft.com/kb/2019667
Je vous recommande également de passer à la version 64 bits de MySQL. Pas de réel raison pour exécuter la version 32 bits plus.
Source: Apache 2.4.6.0 crash en raison d'un problème dans php5ts.dll 5.5.1.0
Erreur fatale: mémoire insuffisante (affectée dans RESOLU
J'ai eu le même problème, pendant des mois, pas de solution. Enfin, j’étais en train de vérifier l’un des dossiers Apache i.e (\ Apache\conf\extra), j’ai rencontré ce fichier qui contrôle l’allocation de mémoire d’Apache. le nom du fichier est httpd-mpm , dans ce fichier, vous devez augmenter la valeur MaxMFree, qui est définie pour 2048, quelque chose de plus élevé. IfModule mpm_netware_module.
Ceux-ci ont résolu mon problème. J'espère que ça aide
Dans le fichier de sortie du profileur, j'ai remarqué deux choses que je n'aimais pas beaucoup/dans lesquelles je ne faisais pas beaucoup confiance et que je voudrais examiner:
Mis à part le fait de ne pas connaître la signification des nombres en sortie pour détecter une anomalie ou le fonctionnement des scripts PHP ..., n'est-ce pas un problème? Avoir une inclusion dans le même fichier main.ph, qui ressemble à une chose récursive?
2121 fl=D:\www\football\views\main.php
2122 fn=include::D:\www\football\views\main.php
Remarqué que le fichier D:\www\football\views\main.php
utilise plusieurs fois des fonctions de chaîne, je suppose qu'il appelle ces fonctions sur les données renvoyées par votre requête:
strlen
substr
strtotime
Si, comme dans le langage C, ces fonctions requièrent des chaînes null
terminées ou une autre terminaison de chaîne pour éviter les problèmes de mémoire, je regarderais les chaînes renvoyées par votre requête.
Pouvez-vous poster l'URL de votre site web?
La plupart du temps, vous obtenez une telle erreur, le problème est dans le code. Je n'essaie pas de dire que vous écrivez du code qui est mauvais, j'essaie de dire que vous devez observer attentivement ce qu'il y a dans l'utilisation de cette quantité de mémoire.
Rappelez-vous toujours que " La récupération de place dans PHP est assez mauvaise ", ce n'est pas comme Java, aucun autre langage de ce type. il existe un moyen d'appliquer la récupération de place via gc_collect_cycle , mais, à mon avis, cela ne résoudra pas votre problème . PHP libère toute la mémoire utilisée pour l'exécution d'une page, une fois le cycle requête-réponse terminé vous risquez donc d’être confronté à des problèmes de mémoire si votre script est long, comme un script en arrière-plan (Gearman, etc.), car la mémoire n’est pas libérée tant que le script n’a pas été exécuté.
Si ce qui précède n'est pas le cas avec votre scr, pt, et comme vous l'avez dit, aucun code ne nécessite une telle quantité de mémoire, alors le problème est très certainement dans le code lui-même et la mise à niveau vers n'importe quelle version de PHP ne résoudra pas le problème. Une fois, j’étais confronté à un de mes scripts Gearman et un problème lié à l’une de mes boucles, j’ajoutais une variable à un de mes tableaux, était très lourd (environ 110 Ko de données). Je suggère donc de faire une inspection minutieuse de votre code.
Ravir
Il s'agit d'un bogue connu dans PHP v 5.2 pour Windows, il est présent au moins jusqu'à la version 5.2.3: https://bugs.php.net/bug.php?id=41615
Aucune des corrections suggérées ne nous a aidé, nous allons devoir mettre à jour PHP.
Les deux faits suivants indiquent clairement des fuites de mémoire:
Je choisirais d'abord PDO, en désactivant toutes les autres extensions et en le laissant fonctionner du jour au lendemain en utilisant quelque chose comme Siege/Apache Bench (ab). Vous pouvez également essayer de l'exécuter en utilisant l'interface cli
(assurez-vous simplement de conserver les mêmes limites de mémoire).
Vous pouvez utiliser la fonction memory_get_peak_usage()
à la fin de votre script pour voir la quantité de mémoire utilisée par PHP.
D'après votre commentaire, 800 Ko, ce qui est correct; certainement pas la quantité de mémoire gigantesque qui causerait un manque de mémoire ;-)
Enfin, bien que je ne recommande pas la mise à niveau vers la version 5.4 pour le moment, la mise à niveau vers la dernière version de la version 5.3.x en vaut probablement la peine en raison des multiples vulnérabilités et fuites corrigées depuis la version 5.3.1
Je dirais que le serveur manque de mémoire physique/d'échange, 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 requête select énorme (des centaines de milliers de résultats renvoyés).
Elle est apparue immédiatement après l’ajout de millions d’enregistrements dans ma base de données pour tester l’évolutivité de WordPress. C’était donc la seule raison probable pour moi.