2010-07-26 4 views
7

J'ai quelques fonctions qui prennent du temps et (potentiellement) beaucoup de mémoire dans mon application web LAMP. La plupart de ces fonctions seront exécutées toutes les minutes via cron (dans certains cas, le travail cron exécutera plusieurs instances de ces fonctions).Gestion de la mémoire PHP

Depuis la mémoire est finie, je ne veux pas rencontrer des problèmes où je suis en train d'exécuter une fonction de l'environnement ne peut plus gérer. Quelle est une bonne approche pour traiter les problèmes de mémoire potentiels?

Je devine que je dois déterminer la quantité de mémoire est disponible pour moi, la quantité de mémoire chaque fonction nécessite avant l'exécuter, de déterminer quelles sont les autres fonctions sont en cours d'exécution par le Cron et leur utilisation de la mémoire, etc.

De même, je ne veux pas rencontrer le problème où une certaine fonction obtient d'une manière ou d'une autre une priorité d'exécution sur d'autres fonctions. Si une priorité est donnée, j'aimerais avoir le contrôle de quelque façon que ce soit.

+1

Plus important encore, pourquoi faites-vous un Cronjob toutes les ** minutes **? Une partie du problème peut être le cron est simpyl essayer d'en faire trop à la fois. Si vous pouviez expliquer le problème et votre solution proposée, nous serions en mesure de donner des réponses mieux faites à votre problème de mémoire spécifique. Il existe différentes approches pour différents problèmes. Est-ce beaucoup de données provenant d'une base de données? Un fichier plat? Simplement une tonne de calculs mathématiques? Chacun aurait ses propres ensembles d'étapes d'optimisation. S'il vous plaît étoffer ce que votre problème est afin que nous puissions donner une réponse appropriée :). – CogitoErgoSum

+0

Je pense que vous devez être plus descriptif et indiquer ce que vous faites dans ce travail cron. Les économies évidentes ne consisteraient pas à charger des fichiers volumineux en mémoire, à utiliser les fonctions de streaming, à extraire un grand ensemble de résultats en mémoire, à utiliser un curseur sur l'ensemble d'enregistrements plutôt que d'extraire toutes les données dans un tableau. –

Répondre

1

vous pouvez regarder dans les technologies de mise en cache comme APC qui vous permet d'écrire des choses à droite dans la RAM afin que vous puissiez y accéder rapidement que l'utilisation si vous ne voulez pas faire des tâches coûteuses telles que les requêtes MySQL à plusieurs reprises.

un exemple pour la mise en cache que je pouvais penser serait que vous pourriez mettre en cache des e-mails plutôt que de les retreiving encore et encore à partir du serveur de messagerie. La mise en mémoire cache basique est une technique très utile si vous avez des choses dans votre script que vous voulez conserver pour la prochaine exécution du script, mais si votre script fait des choses uniques chaque fois qu'il est exécuté, il serait inutile.De même que pour contoll, vous pouvez appeler memory_get_usage() à chaque exécution de script et écrire cette valeur dans le cache apc afin que chaque cron puisse récupérer cette valeur et vérifier si la mémoire est libre. Comme pour une utilisation moyenne, vous pouvez écrire un tableau avec le dernier disons 100 exécutions de fonction et quand vous appelez cette fonction à nouveau, il pourrait apc_fetch cela du RAM et calculer l'utilisation de la mémoire moyenne pour cette fonction, puis le comparer à combien RAM est utilisé en ce moment et décide alors de commencer. de plus, il pourrait écrire cette estimation dans la variable d'utilisation de la mémoire courante pour empêcher l'exécution d'autres scripts. à la fin de cette fonction, vous soustrayez à nouveau cette quantité de la variable. tl; dr: regard sur les fonctions apc_fetch, apc_store et memory_get_usage

+0

Les tâches de taxation de la mémoire ne sont pas liées à MySQL. La plupart d'entre elles concerne le traitement d'images, le traitement PDF, le téléchargement et le téléchargement de fichiers depuis des serveurs FTP, l'envoi et la récupération de courriels, etc. – StackOverflowNewbie

+0

€: j'ai élargi ma réponse pour une meilleure lisibilité –

0

Vous pouvez savoir combien de mémoire est actuellement utilisé par votre script en utilisant memory_get_usage Mais vous ne pouvez pas déterminer à quel point votre fonction suivante devra, avant de l'exécuter. Vous pouvez seulement voir après l'exécution, en utilisant memory_get_usage. Vous pouvez toutefois stocker la mémoire utilisée par votre fonction les dernières fois dans une base de données et calculer avec la quantité de mémoire moyenne.

En ce qui concerne la priorité d'éjection, je ne pense pas qu'il soit possible de déterminer avec PHP. Apache (ou tout autre serveur Web que vous utilisez) génère plusieurs processus et les horaires du système d'exploitation qui seront exécutés dans quel ordre.

+0

'memory_limit' définit la quantité de mémoire que chaque processus php peut consommer. C'est dans votre fichier php.ini. Par défaut, c'est 8 ou 16 Mo. Vous pouvez changer cela à tout moment pour une valeur plus grande, jusqu'à ce que vous ayez assez de mémoire système (+ échange). – Jauzsika

0

Une partie de votre problème peut-être le fait que vous faites un cron chaque minute? Pourquoi ne pas définir des drapeaux afin qu'une seule instance de ce cron soit en cours d'exécution avant qu'un autre exécute la logique complète? c'est-à-dire créer un fichier plat supprimé à la fin du cron pour agir comme un «verrou». Ceci s'assurera qu'un processus de cron se termine complètement avant que d'autres avancent. Cependant, je vous invite à me référer à mon commentaire sur votre message afin que moi et d'autres puissent vous donner des conseils plus solides.

+1

Supposons qu'il y ait une raison légitime pour moi d'exécuter un travail cron chaque minute. – StackOverflowNewbie

0

Essayez d'optimiser vos algorithmes. Comme ...

  • Une fois que vous avez terminé avec une variable que vous devez détruire si vous ne avez plus besoin.
  • Fermez les connexions MySQL après les avoir terminées.
  • Utiliser la récursivité.

Aussi comme Jauzsika a dit changer votre limite de mémoire dans votre php.ini, mais ne le rend pas trop élevé. Si vous avez besoin de plus de 256 Mo de RAM, je vous suggère de changer de langue au lieu de PHP.

+0

Je ne pense pas que vous pouvez spécifier une limite arbitraire de 256 Mo étant donné qu'il n'a pas décrit ce que fait son code. –

+0

Vous avez certainement un point là. – sonikarc

+0

Toutes les variables sont détruites, toutes les connexions DB sont fermées, la récursivité n'est pas une option. 256mb est arbitraire. Il n'y a aucune raison de changer de langue. J'ai juste besoin d'un moyen de m'assurer que je n'utilise pas trop de mémoire par inadvertance. – StackOverflowNewbie

0

Dans votre position, je considérerais l'écriture d'un démon au lieu de compter sur Cron. Le démon peut surveiller une file d'attente et être conscient du nombre de processus enfants qu'il a exécutés. La gestion de plusieurs processus n'est certainement pas la plus grande force de php, mais you can do it. La poire inclut même un paquet System_Daemon.

Votre démon peut utiliser memory_get_usage et appeler free, uptime, et vos amis pour limiter le nombre de travailleurs pour qu'ils correspondent aux conditions du système.

Je n'ai aucune expérience directe avec cela, et je ne serais pas trop surpris si un démon écrit en PHP fuit progressivement la mémoire. Mais si elle est assez lente, cron pourrait faire du cycle du démon de temps en temps ...

+0

... appeler 'memory_get_usage' et communiquer le résultat au parent ... ou peut-être que le parent pourrait appeler' ps' ou 'top' ... – grossvogel