7
votes

Un moyen sans échec d'empêcher la bibliothèque d'images GD de s'épuiser de la mémoire? (Php)

Y a-t-il un moyen d'empêcher le PHP bibliothèque d'images GD de s'épuiser de la mémoire? Si une image trop grande est téléchargée, GD a tendance à manquer de mémoire, à terminer le script. J'aimerais que cela jette une exception capable ou quelque chose à ce prolongement, mais il n'ya pas.

En ce moment, j'utilise un script cobbled-ensemble qui publie d'abord un ini_set ("memory_limit", "128m") , si cela fonctionne, je suis généralement tous ensemble. Selon la configuration du serveur, cependant que cela pourrait ne pas être possible, je suis donc en train de revenir sur un algorithme qui tente d'estimer la quantité de mémoire nécessaire (prise de résolution, de profondeur de couleur, de canaux et d'un facteur de fudge), puis compare-la à memory_get_usage () si la fonction existe, sinon une estimation approximative.

Le tout fonctionne jusqu'à présent, mais il est loin d'être élégant et échouera dans certains cas de bord, je suis sûr. Y a-t-il un meilleur moyen de faire cela, c'est-à-dire que GD échouez gracieusement si cela doit, au lieu de tout grinder à une halte?


2 commentaires

Les grandes images JPEG (non-png ou d'autres types) peuvent être redimensionnées tout en chargement, voir cette réponse pour plus de détails: Stackoverflow.com/Questtions/12661/...


Cela dépendrait de la quantité de RAM que vous avez. Si vous avez 512 Mo de RAM et que vous essayez de redimensionner une image PNG de 10k pixels. Vous toucherez 1,5 Go dans l'utilisation de la RAM presque immédiatement. Ma suggestion est a) Obtenez plus de RAM B) Utilisez des fonctions pour le bâtiment de vos images en les détruisant et utilisez une fonction d'utilisation de la mémoire pour la visualiser à chaque image traitée. Utilisez des fonctions de rinçage pour vider et effacer le tampon ...


6 Réponses :


3
votes

acheter plus de mémoire! :-P

Sérieusement cependant, il est impossible de manipuler la sortie de la mémoire car toute action que vous prenez nécessiterait plus de mémoire.

Votre meilleur pari est de limiter la taille de l'image en cours de téléchargement en fonction des paramètres de mémoire actuels.


1 commentaires

Lol, achetez-moi un hôte avec plus de mémoire. ;-) Eh bien, j'avais au moins comme GD d'estimer sa propre utilisation de la mémoire, au lieu de moi avoir à faire la supposition éviscérée d'erreur, puis retenez mon souffle. Je ne peux pas simplement limiter l'image par taille de fichier. Un petit fichier avec une JPG hautement compressé et haute résolution peut prendre plus de mémoire qu'un gros fichier avec une PNG à basse résolution. C'est pourquoi je dois revenir sur mon calcul mentionné ci-dessus.



0
votes

Votre meilleur pari est d'arrêter d'essayer de déterminer la quantité de RAM dont il aura besoin, et il suffit de le maximiser au début - si vous avez 4 Go, indiquez au script d'image d'utiliser entre 2 et 4 Go. Et lorsque le script se termine, demandez-lui de revenir à la normale, qui couvre toutes les situations potentiellement mortelles. C'est la seule façon "sans échec" que je peux penser de toute façon ...


2 commentaires

C'est ce que j'essaie de faire, mais cela est rarement possible sur les hôtes partagés. Pour ces cas, je fais les calculs de la meilleure hypothèse pour éviter les suspensions.


Réglage de la limite de mémoire PHP égale à la quantité totale de RAM Le système a ou n'importe où à distance à distance, permettra aux utilisateurs de vous sur votre script d'image. Soulignez combien de RAM est nécessaire à l'avance est la seule façon de penser que cela empêchera ce type de DOS.



1
votes

Il y a une autre façon de le faire, mais cela peut consommer du temps, car certaines parties du processus d'édition d'image seraient répétées plusieurs fois, mais vous pouvez définir la limite de mémoire à votre valeur estimée, puis essayer de traiter L'image, si elle échoue à l'exception, augmentez la limite de mémoire, puis traitez l'image à nouveau - répétez-la jusqu'à ce que vous réussissez ou atteignez une certaine limite de mémoire - à quel point vous lanceriez un message d'erreur à l'utilisateur expliquant que leur image expliquait que leur image est trop gros pour être utilisé.

Edit: Pour attraper l'erreur hors mémoire, vous pouvez utiliser cette solution: http: / /au2.php.net/set_error_handler#35622


2 commentaires

Lisez à nouveau, Afaik il n'y a rien de capable d'être jeté. C'est un travail à un coup de feu-ou-it-ne fonctionne pas. À moins que vous ne puissiez me dire comment attraper une erreur hors mémoire, ce que je demande. :)


Je vais devoir voir si cela aide réellement, comme indiqué par Nick, je devrais utiliser plus de mémoire pour faire face à l'erreur après son arrivée.



1
votes

Attraper les erreurs fatales de PHP, comme "Out of Memory" ou "Erreur fatale PHP: Taille de la mémoire autorisée de 8388608 octets épuisés (essayé d'allouer ... des octets) dans", voyez ici: http://php.net/manual/fr/function.set-error-handler.php#88401


1 commentaires

Une fois qu'un script PHP est hors de mémoire, il ne peut pas appeler la fonction d'arrêt car cela nécessiterait la répartition de la mémoire plus.



2
votes

Après avoir créé une image.

imagepng($image);
imagedestroy($image);


3 commentaires

Cela devrait être marqué comme la réponse, cela a fonctionné comme un charme pour moi.


Cela devrait pas marqué comme réponse. Détruire une image permet d'économiser de la mémoire, mais ne fait en aucun cas que GD se comporter de manière plus gracieuse.


Downvote. Ce n'est pas une solution, mais une procédure standard pour éviter les fuites de mémoire. Il n'arrêtera pas GD de provoquer un débordement de la mémoire si une seule image est déjà assez grande pour atteindre la limite de mémoire.



1
votes

Faites quelques tests pour vérifier la quantité de mémoire chaque gd besoin.

  • imagecreateTuecolor semble avoir besoin largeur * hauteur * 5 octets .

  • imagepng semble avoir besoin largeur * hauteur * 4 octets .


4 commentaires

Pourquoi IMAGECEATURECOLOR Besoin de 5 octets par pixel? Cela ressemble à un nombre impair.


Parce que le soutien alpha a été ajouté longtemps après l'imagecreate, et beaucoup de fonctions avaient probablement des hypothèses que le 4ème octet était toujours 0, donc il ne pouvait pas être utilisé ... ou ils pensaient que c'était trop complexe pour l'utiliser et créé un nouveau.


Avez-vous également une expérience lorsque vous chargez des images existantes en plus? par exemple. pour jpg ou png? J'utilise X * Y * ~ 5 pour JPG, ~ 8 pour PNG, en haut de l'utilisation du MEM actuel. Si cela dépasse la limite de MEM, je définit une exception. Mais: définir 64 m comme limite et avoir une JPG téléchargée de 2 Mo peut parfois casser l'opération. JPG semble utiliser parfois plus de mémoire. Compression? Toute autre donnée exif? Où puis-je améliorer le calcul?


Tous les appels vers ImagePng, ImageJPEG, ImageGIF, ImageBMP, ImageWBMP, ImageXBM, ImageWEBP, ImageGD, ImageGD2 utiliseront la largeur * Hauteur * Certains octets de la COEF, en plus des ressources actuelles existantes (à partir de tout l'imagecreate, ImagecreeTuecolor et Imagecreefrom *) (et Peut-être une mémoire temporaire pour la compression, le format et tous). Imageloadfont & ImagePsPloadfont utilisera également une certaine mémoire. L'ancienne ressource doit être détruite avec Imdestroy pour éviter les fuites.