48 votes

Conseils pour limiter l'utilisation de la mémoire Perl

Quels sont les bons conseils pour garder la mémoire d'utilisation de la basse dans un script Perl? Je suis intéressé à apprendre comment garder ma mémoire, aussi bas que possible pour les systèmes selon les programmes Perl. Je sais que Perl n'est pas génial quand il s'agit de l'utilisation de la mémoire, mais je voudrais savoir si il y a des conseils pour l'améliorer.

Alors, que pouvez-vous faire pour garder un script Perl qui utilise moins de mémoire. Je suis intéressé par toutes les suggestions, s'ils sont réels conseils pour l'écriture de code, ou des conseils pour savoir comment compiler Perl différemment.

Edit pour Bounty: J'ai un programme en perl qui sert de serveur pour une application réseau. Chaque client qui se connecte à elle obtienne sa propre processus enfant actuellement. J'ai utilisé les threads au lieu de fourches ainsi, mais je n'ai pas été en mesure de déterminer si l'utilisation de threads au lieu de fourche est en fait plus efficace en terme de mémoire.

Je voudrais essayer de l'utilisation de threads au lieu de fourchettes de nouveau. Je crois en théorie, il devrait enregistrer sur l'utilisation de la mémoire. J'ai quelques questions à ce sujet:

  1. Ne threads créés en Perl empêcher la copie des bibliothèques de modules Perl en mémoire pour chaque thread?
  2. Est fils (fils) le moyen le plus efficace (ou la seule) façon de créer des threads en Perl?
  3. Dans les discussions, je peux spécifier un stack_size paramater, qu'est-ce spécifiquement dois-je considérer lors de la spécification de cette valeur, et quelle est son incidence l'utilisation de la mémoire?

Avec les threads en Perl/Linux, ce qui est la méthode la plus fiable pour déterminer le montant réel de l'utilisation de la mémoire sur une base par thread?

80voto

brian d foy Points 71781

Quel type de problème vous êtes en cours d'exécution, et que signifie "grand" signifie pour vous? J'ai des amis, vous devez charger 200 Go de fichiers en mémoire, de sorte que leur idée de bons conseils est très différent que le budget shopper pour un minimum de VM tranches de souffrance avec 250 Mo de RAM (vraiment? Mon téléphone a plus que cela).

En général, Perl, tient toute la mémoire que vous utilisez, même si il ne l'utilise pas. Réaliser que l'optimisation de la dans une direction, par exemple la mémoire, pourrait avoir un impact négatif de l'autre, comme la vitesse.

Ce n'est pas une liste exhaustive (et il n'y a plus de Programmation Perl):

☹ Utiliser Perl le profilage de la mémoire d'outils pour vous aider à trouver les zones à problème. Voir le Profilage des tas utilisation de la mémoire sur les programmes perl et Comment trouver la quantité de mémoire physique occupé par une table de hachage en Perl?

☹ Utiliser des variables lexicales avec le plus petit périmètre possible afin de permettre à Perl pour la ré-utilisation de la mémoire lorsque vous n'en avez pas besoin.

☹ Éviter de créer de grandes structures temporaires. Par exemple, la lecture d'un fichier avec un foreach lit toutes les entrées à la fois. Si vous avez seulement besoin de ligne-par-ligne, while.

 foreach ( <FILE> ) { ... } # list context, all at once 
 while( <FILE> ) { ... } # scalar context, line by line

☹ Vous pourriez même pas besoin d'avoir le fichier en mémoire. Carte mémoire les fichiers au lieu d'aspirer eux

☹ Si vous avez besoin pour créer des structures de données, pensez à quelque chose comme DBM::Profonde ou d'autres moteurs de stockage pour garder la plupart de la mémoire vive et sur le disque jusqu'à ce que vous en avez besoin.

☹ Ne pas laisser les gens utiliser votre programme. Chaque fois que je l'ai fait, j'ai réduit l'empreinte mémoire d'environ 100%. Il réduit également sur les demandes de support.

☹ Passer de gros morceaux de texte et de grands agrégats de référence afin de ne pas faire une copie, ainsi stocker deux fois la même information. Si vous avez à le copier parce que vous voulez changer quelque chose, vous pourriez être coincé. Cela va dans les deux sens comme sous-routine arguments et les valeurs de retour de sous-routine:

 call_some_sub( \$big_text, \@long_array );
 sub call_some_sub {
      my( $text_ref, $array_ref ) = @_;
      ...
      return \%hash;
      }

☹ Traquer les fuites de mémoire dans les modules. J'ai eu de gros problèmes avec une application jusqu'à ce que j'ai réalisé qu' un module n'était pas la libération de la mémoire. J'ai trouvé un patch dans le module de la RT file d'attente, appliqué, et résolu le problème.

☹ Si vous avez besoin de gérer un gros morceau de données une fois, mais ne veulent pas de la persistance de la mémoire, de confier les travaux à un processus enfant. Le processus de l'enfant a seulement l'empreinte mémoire pendant qu'il tourne. Lorsque vous obtenez la réponse, le processus de l'enfant s'arrête et la libère de la mémoire. De même, le travail des systèmes de distribution de Gearman, peut se propager de travail entre les machines.

☹ Tour récursive des solutions dans itératif ceux. Perl n'a pas de queue à la récursivité d'optimisation, de sorte que chaque nouveau téléphone, qui s'ajoute à la pile d'appel. Vous pouvez optimiser la queue problème vous-même avec les trucs avec le goto ou d'un module, mais c'est beaucoup de travail pour accrocher une technique que vous n'avez probablement pas besoin.

☹ N'a-t-il 6 Go ou seulement cinq? Eh bien, pour vous dire la vérité, dans toute cette excitation j'ai un peu perdu la trace de moi-même. Mais comme c'est du Perl, le plus puissant de la langue dans le monde, et pourrait faire exploser votre propre mémoire, vous avez obtenu de vous poser une question: j'ai de la chance? Eh bien, pensez-ay, le punk?

Il ya beaucoup plus, mais il est trop tôt dans la matinée pour comprendre ce que ceux qui sont. Je couvre certains en Mastering Perl et Efficace de Programmation Perl.

4voto

pizza Points 2855

Mes deux dimes.

  1. Ne threads créés en Perl empêcher la copie module Perl bibliothèques en mémoire pour chaque thread?

    • Il n'est pas, il est juste un processus, ce qui n'est pas répété dans la pile du programme, chaque thread doit avoir sa propre.
  2. Est fils (fils) le moyen le plus efficace (ou la seule) façon de créer des threads en Perl?

    • OMI Toute méthode appelle éventuellement la bibliothèque pthread Api qui fait réellement le travail.
  3. Dans les discussions, je peux spécifier un stack_size paramater, que doit-je considérer lors de l' la spécification de cette valeur, et quelle est son incidence sur l'utilisation de la mémoire?

    • Etant donné que les threads s'exécute dans le même espace de processus, la pile ne peut pas être partagé. La taille de la pile raconte pthreads à quelle distance ils devraient être les uns des autres. Chaque fois qu'une fonction est appelée les variables locales sont allouées sur la pile. Si la taille de la pile des limites de profondeur de manière récursive. vous pouvez allouer aussi peu que possible de l'étendre que votre application fonctionne toujours.

Avec les threads en Perl/Linux, ce qui est la méthode la plus fiable pour déterminer le montant réel de l'utilisation de la mémoire sur une base par thread?

* Stack storage is fixed after your thread is spawned, heap and static storage is shared and
  they can be used by any thread so this notion of memory usage per-thread doesn't really
  apply. It is per process.


Comparing fork and thread:

* fork duplicate the process and inherites the file handles

  advantages: simpler application logic, more fault tolerant.
              the spawn process can become faulty and leaking resource
              but it will not bring down the parent. good solution if
              you do not fork a lot and the forked process eventually
              exits and cleaned up by the system.

  disadvantages: more overhead per fork, system limitation on the number
              of processes you can fork. You program cannot share variables.

* threads runs in the same process with addtional program stacks.

  advantages: lower memory footprint, thread spawn if faster and ligther
              than fork. You can share variables.

  disadvantages: more complex application logic, serialization of resources etc.
              need to have very reliable code and need to pay attention to
              resource leaks which can bring down the entire application.

IMO, depends on what you do, fork can use way less memory over the life time of the 
application run if whatever you spawn just do the work independently and exit, instead of
risking memory leaks in threads.

2voto

Øyvind Skaar Points 1291

Si vous êtes vraiment désespéré, vous pourriez essayer de monter la mémoire comme un système de fichierstmpfs/ramdisk) et de lire/écrire/supprimer des fichiers sur elle. Je suppose que le tmpfs mise en œuvre est assez intelligent pour libérer de la mémoire lorsque vous supprimez un fichier.

Vous pouvez également mmap (voir le Fichier::Map, Sys::Mmap) un énorme fichier sur le tmpfs, une idée que j'ai eu de Cache::FastMmap.

Jamais essayé, mais cela devrait fonctionner :)

1voto

bluescreen Points 887

Les deux fils et la fourche sera CoW (Copy on Write) pages de mémoire. Avec les threads, vous pouvez défini des variables partagées, mais par défaut de copie vos variables par sujet. Dans les deux cas, vous pouvez vous attendre à une plus grande utilisation de la mémoire.

Je ne sais pas exactement quel type de demande que vous faites affaire avec, mais vous pouvez envisager d'écrire votre Application à l'aide Événement Piloté par le modèle au lieu de Parent/Enfant de processus. Je vous recommande de prendre un coup d'oeil à AnyEvent c'est assez simple, et compte tenu de l'application devient thread unique ( ou processus ), vous allez économiser de la mémoire (et encore plus vite dans certains cas). Les gens même écrit des serveurs avec AnyEvent avec de très bonnes performances et vous pourriez presque pas remarqué qu'il est mono-thread. Jetez un oeil par exemple pour Twiggy

-7voto

ppant Points 463

Essayez d'utiliser plus de cache. La logique d'implémentation de la routine de mise en cache est toujours la même, ce qui vous permet d'automatiser l'utilisation du module CPAN Memoize . Utilisez Devel :: Size pour vérifier l’empreinte mémoire réelle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X