web-dev-qa-db-fra.com

Augmenter PHP memory_limit. À quel moment devient-il fou?

Dans un système sur lequel je travaille actuellement, il existe un processus qui charge une grande quantité de données dans un tableau pour le tri/l'agrégation/peu importe. Je sais que ce processus doit être optimisé pour l'utilisation de la mémoire, mais à court terme, il doit simplement fonctionner.

Étant donné la quantité de données chargées dans le tableau, nous continuons à atteindre la limite de mémoire. Il a été augmenté plusieurs fois, et je me demande s'il y a un point où l'augmentation devient généralement une mauvaise idée? ou est-ce seulement une question de combien RAM la machine a-t-elle?

La machine a 2 Go de RAM et le memory_limit est actuellement fixé à 1,5 Go. Nous pouvons facilement ajouter plus RAM à la machine (et le fera de toute façon).

D'autres ont-ils rencontré ce type de problème? et quelles ont été les solutions?

38
Brenton Alker

La configuration de memory_limit of PHP fonctionnant en tant que module Apache sur les pages Web du serveur doit prendre en compte le nombre de processus Apache que vous pouvez avoir en même temps sur la machine - voir MaxClients option de configuration pour Apache.

Si MaxClients est égal à 100 et que vous avez 2000 Mo de RAM, un calcul très rapide montrera que vous ne devez pas utiliser plus de 20 Mo * (car 20 Mo * 100 clients = 2 Go ou RAM, soit le montant total de mémoire de votre serveur) * pour la valeur memory_limit.

Et c'est sans considérer qu'il y a probablement d'autres choses qui tournent sur le même serveur, comme MySQL, le système lui-même, ... Et qu'Apache utilise probablement déjà de la mémoire pour lui-même.

Ou bien sûr, c'est aussi un "pire scénario", qui considère que chaque page PHP utilise la quantité maximale de mémoire possible).


Dans votre cas, si vous avez besoin d'une telle quantité de mémoire pour un seul travail, je n'augmenterais pas le memory_limit pour PḦP fonctionnant en tant que module Apache.

Au lieu de cela, je lancerais ce travail à partir de la ligne de commande (ou via un travail cron), et spécifierais un memory_limit spécifiquement dans ce seul et unique cas.

Cela peut être fait avec le -d option de php, comme:

$ php -d memory_limit=1GB temp.php
string(3) "1GB"

Considérant, dans ce cas, que temp.php ne contient que:

var_dump(ini_get('memory_limit'));

À mon avis, c'est beaucoup plus sûr que d'augmenter la mémoire_limit pour le PHP pour Apache - et c'est ce que je fais habituellement quand j'ai un grand ensemble de données, ou des trucs vraiment lourds que je ne peux pas optimiser ou paginer.


Si vous devez définir plusieurs valeurs pour l'exécution PHP CLI, vous pouvez également lui dire d'utiliser un autre fichier de configuration, au lieu du php.ini par défaut, avec le -c option:

php -c /etc/phpcli.ini temp.php

De cette façon, vous avez:

  • /etc/php.ini pour Apache, avec un faible memory_limit, faible max_execution_time, ...
  • et /etc/phpcli.ini pour les lots exécutés à partir de la ligne de commande, sans pratiquement aucune limite

Cela garantit que vos lots pourront s'exécuter - et vous aurez toujours la sécurité de votre site Web (memory_limit et max_execution_time étant des mesures de sécurité)


Pourtant, si vous avez le temps d'optimiser votre script, vous devriez; par exemple, dans ce genre de situation où vous devez gérer beaucoup de données, la pagination est un must-have ;-)

56
Pascal MARTIN

Avez-vous essayé de diviser l'ensemble de données en parties plus petites et de ne traiter qu'une seule partie à la fois?

Si vous récupérez les données d'un fichier disque, vous pouvez utiliser la fonction fread() pour charger des morceaux plus petits, ou certains sorte de requête db sans tampon au cas où de la base de données.

Je n'ai pas vérifié PHP depuis v3.quelque chose, mais vous pouvez également utiliser une forme de cloud computing. Le jeu de données de 1 Go semble être assez grand pour être traité sur plusieurs machines.

2
arul

Étant donné que vous savez qu'il y a des problèmes de mémoire avec votre script qui doivent être corrigés et que vous ne cherchez que des solutions à court terme, alors je n'aborderai pas les moyens de aller sur le profilage et de résoudre vos problèmes de mémoire . On dirait que vous allez y arriver.

Donc, je dirais que les principales choses à garder à l'esprit sont:

  • Charge totale de mémoire sur le système
  • Capacités du système d'exploitation

PHP n'est qu'un petit composant du système. Si vous lui permettez de consommer une grande quantité de votre RAM, les autres processus en souffriront, ce qui pourrait à son tour affecter le script lui-même. Notamment, si vous extrayez beaucoup de données d'une base de données, votre SGBD peut nécessiter beaucoup de mémoire pour créer des jeux de résultats pour vos requêtes. En guise de solution rapide, vous souhaiterez peut-être identifier toutes les requêtes que vous exécutez et libérer les résultats dès que possible pour vous donner plus de mémoire pour un long travail.

En termes de capacités du système d'exploitation, vous devez garder à l'esprit que les systèmes 32 bits, sur lesquels vous êtes probablement en cours d'exécution, ne peuvent traiter que jusqu'à 4 Go de RAM sans traitement spécial. Souvent, la limite peut être beaucoup moins en fonction de la façon dont il est utilisé. Certains chipsets et configurations Windows peuvent avoir moins de 3 Go disponibles sur le système, même avec 4 Go ou plus physiquement installés. Vous devriez vérifier pour voir combien votre système peut gérer.

Vous dites que vous avez augmenté la limite de mémoire à plusieurs reprises, de sorte que ce travail est de plus en plus étendu. Si vous êtes jusqu'à 1,5 Go, alors même l'installation de 2 Go de plus RAM sonne comme si ce ne serait qu'un court sursis.

D'autres ont-ils rencontré ce type de problème? et quelles ont été les solutions?

Je pense que vous savez probablement déjà que la seule vraie solution est de tomber en panne et de passer le temps d'optimiser le script bientôt, ou vous vous retrouverez avec un travail qui sera trop gros pour être exécuté.

1
zombat