Réduction de l'utilisation de la mémoire Django. Fruits mûrs?

136

Mon utilisation de la mémoire augmente avec le temps et le redémarrage de Django n'est pas gentil avec les utilisateurs.

Je ne sais pas comment établir le profil de l'utilisation de la mémoire, mais quelques conseils sur la façon de commencer à mesurer seraient utiles.

J'ai le sentiment qu'il y a quelques étapes simples qui pourraient produire de gros gains. S'assurer que «debug» est défini sur «False» est une évidence.

Quelqu'un peut-il en suggérer d'autres? Quelle amélioration apporterait la mise en cache sur les sites à faible trafic?

Dans ce cas, je cours sous Apache 2.x avec mod_python. J'ai entendu dire que mod_wsgi est un peu plus léger mais il serait difficile de changer à ce stade à moins que je sache que les gains seraient significatifs.

Edit: Merci pour les conseils jusqu'à présent. Des suggestions pour découvrir ce qui utilise la mémoire? Existe-t-il des guides sur le profilage de la mémoire Python?

De plus, comme mentionné, il y a quelques choses qui rendront difficile le passage à mod_wsgi, donc j'aimerais avoir une idée des gains auxquels je pourrais m'attendre avant de continuer dans cette direction.

Edit: Carl a posté ici une réponse un peu plus détaillée qui vaut la peine d'être lue: Django Deployment: Cutting Apache's Overhead

Edit: L'article de Graham Dumpleton est le meilleur que j'ai trouvé sur le MPM et les trucs liés à mod_wsgi. Je suis plutôt déçu que personne n'ait pu fournir d'informations sur le débogage de l'utilisation de la mémoire dans l'application elle-même.

Final Edit: Eh bien, j'en ai discuté avec Webfaction pour voir s'ils pourraient aider à recompiler Apache et c'est leur mot à ce sujet:

"Je ne pense vraiment pas que vous obtiendrez beaucoup d'avantages en passant à une configuration MPM Worker + mod_wsgi. J'estime que vous pourriez économiser environ 20 Mo, mais probablement pas beaucoup plus que cela."

Alors! Cela me ramène à ma question initiale (dont je ne suis toujours pas plus sage). Comment identifier les problèmes? C'est une maxime bien connue que vous n'optimisez pas sans tester pour voir où vous devez optimiser, mais il y a très peu de tutoriels sur la mesure de l'utilisation de la mémoire Python et aucun n'est spécifique à Django.

Merci pour l'aide de tous mais je pense que cette question est toujours ouverte!

Encore une dernière modification ;-)

J'ai posé cette question sur la liste des utilisateurs de django et j'ai obtenu des réponses très utiles

Honnêtement, la dernière mise à jour de tous les temps!

Cela vient juste d'être publié. Pourrait être la meilleure solution à ce jour: profiler la taille de l'objet Django et l'utilisation de la mémoire avec Pympler

Andy Baker
la source

Réponses:

50

Assurez-vous de ne pas conserver de références globales aux données. Cela empêche le garbage collector python de libérer la mémoire.

N'utilisez pas mod_python. Il charge un interpréteur dans apache. Si vous avez besoin d'utiliser apache, utilisez à la mod_wsgiplace. Il n'est pas difficile de changer. C'est très facile. mod_wsgiest bien plus facile à configurer pour django que de mort cérébrale mod_python.

Si vous pouvez supprimer Apache de vos exigences, ce serait encore mieux pour votre mémoire. spawningsemble être le nouveau moyen évolutif rapide d'exécuter des applications Web python.

EDIT : Je ne vois pas comment passer à mod_wsgi pourrait être " délicat ". Cela devrait être une tâche très facile. Veuillez expliquer le problème que vous rencontrez avec le commutateur.

nosklo
la source
4
@Josh: le gonflement et l'utilisation de la mémoire d'Apache sont stupides si vous n'utilisez pas uniquement les fonctionnalités d'Apache. C'est juste une couche inutile.
nosklo
3
Django approuve toujours mod_python car mod_wsgi est encore assez récent, et ils veulent être conservateurs. Mais si vous suivez la communauté Django, vous verrez des gens passer en masse à mod_wsgi. Cela ne prendra pas longtemps avant que ce soit l'option recommandée.
Carl Meyer
1
@Tiago: apache est bon quand vous avez déjà beaucoup d'hôtes virtuels apache en place, utilisant déjà SSL avec apache, etc. Dans ce cas, utilisez mod_wsgi. Si vous recommencez, utilisez le frai. N'utilisez JAMAIS mod_python.
nosklo
1
Merci, nosklo. Je jette un oeil à spawning .. semble avoir peu ou pas de documentation .. Je vais essayer de suivre quelques instructions que j'ai trouvées dans les articles de blog et voir où je peux obtenir.
Tiago
1
Hmm, comme quelqu'un qui commence tout juste à utiliser Django, je garderai à l'esprit que je devrais utiliser mod_wsgi.
Powerlord
28

Si vous exécutez sous mod_wsgi et que vous vous reproduisez probablement car il est compatible WSGI, vous pouvez utiliser Dozer pour examiner votre utilisation de la mémoire.

Sous mod_wsgi, ajoutez simplement ceci au bas de votre script WSGI:

from dozer import Dozer
application = Dozer(application)

Puis pointez votre navigateur sur http: // domain / _dozer / index pour voir une liste de toutes vos allocations de mémoire.

J'ajouterai aussi simplement ma voix de soutien pour mod_wsgi. Cela fait toute la différence en termes de performances et d'utilisation de la mémoire sur mod_python. Le support de Graham Dumpleton pour mod_wsgi est exceptionnel, à la fois en termes de développement actif et en aidant les personnes figurant sur la liste de diffusion à optimiser leurs installations. David Cramer de curse.com a publié des graphiques (que je ne parviens malheureusement pas à trouver maintenant) montrant la réduction drastique de l'utilisation du processeur et de la mémoire après le passage à mod_wsgi sur ce site à fort trafic. Plusieurs développeurs de django ont changé. Sérieusement, c'est une évidence :)

Van Gale
la source
Dans ce cas, je posterai bientôt une question demandant comment on obtient l'authentification basée sur les cookies pour les utilisateurs de django accédant à des fichiers statiques ...
Andy Baker
15

Voici les solutions de profileur de mémoire Python que je connais (non liées à Django):

Avertissement: J'ai un intérêt dans ce dernier.

La documentation du projet individuel devrait vous donner une idée de la façon d'utiliser ces outils pour analyser le comportement de la mémoire des applications Python.

Ce qui suit est une belle "histoire de guerre" qui donne également quelques conseils utiles:

Pankrat
la source
5

De plus, vérifiez si vous n'utilisez aucun des fuites connus. MySQLdb est connu pour laisser échapper d'énormes quantités de mémoire avec Django en raison d'un bogue dans la gestion Unicode. En dehors de cela, Django Debug Toolbar peut vous aider à suivre les porcs.

zgoda
la source
amix.dk/blog/viewEntry/19420 montre que le bulldozer est utilisé pour montrer que MySQLdb fuyait de la mémoire. MySQLdb 1.2.3c1 et versions ultérieures corrige ce problème.
msanders
Comment pourrait django-debug-toolbaraider?
Wtower
4

En plus de ne pas conserver de références globales à de gros objets de données, essayez d'éviter de charger de grands ensembles de données en mémoire dans la mesure du possible.

Basculez vers mod_wsgi en mode démon et utilisez le worker mpm d'Apache au lieu de prefork. Cette dernière étape peut vous permettre de servir beaucoup plus d'utilisateurs simultanés avec beaucoup moins de mémoire.

Carl Meyer
la source
Voir également la réponse de Carl ici: stackoverflow.com/questions/488864/…
Andy Baker
Aussi - dans quelques articles que j'ai lus, il semble que le vrai gain est de passer au MPM travailleur plutôt que d'utiliser mod_wsgi ...
Andy Baker
4

Webfaction a en fait quelques astuces pour réduire l'utilisation de la mémoire de django.

Les points majeurs:

  • Assurez-vous que le débogage est défini sur false (vous le savez déjà).
  • Utilisez "ServerLimit" dans votre configuration Apache
  • Vérifiez qu'aucun gros objet n'est chargé en mémoire
  • Envisagez de diffuser du contenu statique dans un processus ou un serveur distinct.
  • Utilisez "MaxRequestsPerChild" dans votre configuration Apache
  • Découvrez et comprenez la quantité de mémoire que vous utilisez
Jason Baker
la source
2
Merci, j'avais déjà lu ceux-ci. Ce sont les numéros 3 et 6 sur lesquels j'espérais un peu plus de détails! ;-)
Andy Baker
3

Un autre avantage pour mod_wsgi: définissez un maximum-requestsparamètre dans votre WSGIDaemonProcessdirective et mod_wsgi redémarrera le processus démon de temps en temps. Il ne devrait y avoir aucun effet visible pour l'utilisateur, autre qu'un chargement de page lent la première fois qu'un nouveau processus est lancé, car il chargera Django et le code de votre application en mémoire.

Mais même si vous n'avez des fuites de mémoire, qui devraient maintenir la taille du processus de devenir trop grand, sans avoir à le service d' interruption à vos utilisateurs.

AdamKG
la source
1
Quelque chose de similaire est mentionné ici: mail-archive.com/[email protected]/msg84698.html seulement ils ont utilisé inactivity-timeout au lieu de maximum-requests.
Tomas Andrle
3

Voici le script que j'utilise pour mod_wsgi (appelé wsgi.py, et mis à la racine de mon projet django):

import os
import sys
import django.core.handlers.wsgi

from os import path

sys.stdout = open('/dev/null', 'a+')
sys.stderr = open('/dev/null', 'a+')

sys.path.append(path.join(path.dirname(__file__), '..'))

os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
application = django.core.handlers.wsgi.WSGIHandler()

Ajustez myproject.settings et le chemin si nécessaire. Je redirige toute la sortie vers / dev / null car mod_wsgi par défaut empêche l'impression. Utilisez plutôt la journalisation.

Pour apache:

<VirtualHost *>
   ServerName myhost.com

   ErrorLog /var/log/apache2/error-myhost.log
   CustomLog /var/log/apache2/access-myhost.log common

   DocumentRoot "/var/www"

   WSGIScriptAlias / /path/to/my/wsgi.py

</VirtualHost>

J'espère que cela devrait au moins vous aider à configurer mod_wsgi afin que vous puissiez voir si cela fait une différence.

Staale
la source
1

Caches: assurez-vous qu'ils sont vidés. Il est facile pour quelque chose d'atterrir dans un cache, mais ne sera jamais GC à cause de la référence du cache.

Code swig'd: assurez-vous que la gestion de la mémoire est effectuée correctement, il est vraiment facile de les manquer en python, en particulier avec des bibliothèques tierces

Surveillance: si vous le pouvez, obtenez des données sur l'utilisation de la mémoire et les appels. Habituellement, vous verrez une corrélation entre un certain type de demande et l'utilisation de la mémoire.

Richard Levasseur
la source
1

Nous sommes tombés sur un bug dans Django avec de gros plans de site (10 000 éléments). Il semble que Django essaie de tous les charger en mémoire lors de la génération du plan du site: http://code.djangoproject.com/ticket/11572 - tue efficacement le processus Apache lorsque Google visite le site.

Emil Stenström
la source