Reduzindo o uso de memória do Django. Frutos mais baixos?

136

Meu uso de memória aumenta com o tempo e reiniciar o Django não é bom para os usuários.

Não tenho certeza de como fazer o perfil do uso da memória, mas algumas dicas sobre como começar a medir seriam úteis.

Sinto que existem alguns passos simples que podem produzir grandes ganhos. Garantir que 'debug' esteja definido como 'False' é um óbvio óbvio.

Alguém pode sugerir outros? Quanta melhoria o cache teria em sites de baixo tráfego?

Nesse caso, estou executando o Apache 2.x com mod_python. Ouvi dizer que mod_wsgi é um pouco mais enxuto, mas seria complicado mudar nesse estágio, a menos que eu saiba que os ganhos seriam significativos.

Edit: Obrigado pelas dicas até agora. Alguma sugestão de como descobrir o que está consumindo a memória? Existem guias para criação de perfil de memória Python?

Além disso, como mencionado, há algumas coisas que tornarão difícil mudar para mod_wsgi, então eu gostaria de ter uma idéia dos ganhos que eu poderia esperar antes de avançar nessa direção.

Edit: Carl postou aqui uma resposta um pouco mais detalhada que vale a pena ler: Django Deployment: Cutting Overhead of Apache

Edit: O artigo de Graham Dumpleton é o melhor que eu encontrei no MPM e no mod_wsgi. Estou um pouco decepcionado que ninguém possa fornecer informações sobre a depuração do uso de memória no próprio aplicativo.

Edição final: Bem, eu tenho discutido isso com o Webfaction para ver se eles poderiam ajudar na recompilação do Apache e esta é a palavra deles sobre o assunto:

"Realmente não acho que você obterá muitos benefícios mudando para uma configuração MPM Worker + mod_wsgi. Estimo que você poderá economizar cerca de 20 MB, mas provavelmente não muito mais que isso."

Assim! Isso me leva de volta à minha pergunta original (sobre a qual ainda não sou o mais sábio). Como se identifica onde estão os problemas? É uma máxima bem conhecida que você não otimiza sem testar para ver onde precisa otimizar, mas há muito pouco no caminho de tutoriais sobre como medir o uso de memória Python e nenhum específico sobre o Django.

Obrigado pela ajuda de todos, mas acho que essa pergunta ainda está aberta!

Outra edição final ;-)

Eu perguntei isso na lista django-users e recebi algumas respostas muito úteis

Honestamente, a última atualização de sempre!

Isso acabou de ser lançado. Pode ser a melhor solução até o momento: criação de perfil do tamanho do objeto Django e uso de memória com o Pympler

Andy Baker
fonte

Respostas:

50

Certifique-se de não manter referências globais aos dados. Isso impede que o coletor de lixo python libere a memória.

Não use mod_python. Carrega um intérprete dentro do apache. Se você precisar usar o apache, use mod_wsgi. Não é complicado mudar. Isso é muito fácil. mod_wsgié muito mais fácil de configurar para django do que com morte cerebral mod_python.

Se você pode remover o apache de seus requisitos, isso seria ainda melhor para sua memória. spawningparece ser a nova maneira rápida e escalável de executar aplicativos da web python.

Edição : Eu não vejo como mudar para mod_wsgi pode ser " complicado ". Deve ser uma tarefa muito fácil. Por favor, elabore o problema que você está tendo com a opção.

nosklo
fonte
4
@ Josh: o inchaço e o uso de memória do apache são estúpidos se você não estiver usando recursos exclusivos do apache. É apenas uma camada desnecessária.
Nosklo 28/01/09
3
O Django ainda apoia o mod_python porque o mod_wsgi ainda é relativamente novo e eles querem ser conservadores. Mas se você seguir a comunidade Django, verá pessoas mudando para mod_wsgi em massa. Não demorará muito para que seja a opção recomendada.
246 Carl
1
@Tiago: o apache é bom quando você já possui muitos hosts virtuais do apache, usando SSL com o apache, etc. Nesse caso, use mod_wsgi. Se você estiver começando novamente, use a desova. NUNCA use mod_python.
Nosklo 29/01/09
1
Obrigado, nosklo. Estou analisando a desova ... parece ter pouca ou nenhuma documentação .. Vou tentar seguir algumas instruções que encontrei nas postagens do blog e ver onde posso obter.
Tiago
1
Hmm, como alguém que está começando a usar o Django, vou lembrar que devo usar o mod_wsgi.
Powerlord 30/01
28

Se você estiver executando o mod_wsgi e provavelmente estiver gerando uma vez que é compatível com WSGI, poderá usar o Dozer para verificar o uso da memória.

Sob mod_wsgi, adicione isso na parte inferior do seu script WSGI:

from dozer import Dozer
application = Dozer(application)

Em seguida, aponte seu navegador para http: // domain / _dozer / index para ver uma lista de todas as suas alocações de memória.

Também adicionarei minha voz de suporte ao mod_wsgi. Faz muita diferença em termos de desempenho e uso de memória sobre o mod_python. O suporte de Graham Dumpleton ao mod_wsgi é excelente, tanto em termos de desenvolvimento ativo quanto em ajudar as pessoas na lista de discussão a otimizar suas instalações. David Cramer, do curse.com , publicou alguns gráficos (que infelizmente não consigo encontrar agora) mostrando a drástica redução no uso da CPU e da memória depois que eles mudaram para mod_wsgi naquele site de alto tráfego. Vários dos desenvolvedores do django mudaram. Sério, é um acéfalo :)

Van Gale
fonte
Caso em que em breve vou postar uma pergunta perguntando como se obtém a autenticação baseada em cookie para Django usuários que acessam arquivos estáticos ...
Andy Baker
15

Estas são as soluções de perfilador de memória de Python que eu conheço (não relacionadas ao Django):

Disclaimer: Eu tenho uma participação neste último.

A documentação do projeto individual deve fornecer uma idéia de como usar essas ferramentas para analisar o comportamento da memória dos aplicativos Python.

A seguir, uma boa "história de guerra" que também fornece algumas dicas úteis:

Pankrat
fonte
5

Além disso, verifique se você não usa nenhum dos vazamentos conhecidos. Sabe-se que o MySQLdb vaza enormes quantidades de memória com o Django devido a erros no manuseio unicode. Fora isso, a Django Debug Toolbar pode ajudá-lo a rastrear os porcos.

zgoda
fonte
amix.dk/blog/viewEntry/19420 mostra o dozer sendo usado para mostrar que o MySQLdb estava vazando memória. O MySQLdb 1.2.3c1 e posterior corrigem isso.
msanders
Como poderia django-debug-toolbarajudar?
Wtower 29/10/2015
4

Além de não manter referências globais a objetos de dados grandes, tente evitar carregar grandes conjuntos de dados na memória sempre que possível.

Alterne para mod_wsgi no modo daemon e use o mpm de trabalho do Apache em vez do prefork. Esta última etapa pode permitir que você atenda muito mais usuários simultâneos com muito menos sobrecarga de memória.

Carl Meyer
fonte
Veja também a resposta de Carl aqui: stackoverflow.com/questions/488864/…
Andy Baker
Também - em alguns lugares que eu li, parece que o ganho real é na mudança para MPM trabalhador ao invés do uso de mod_wsgi ...
Andy Baker
4

O Webfaction, na verdade, tem algumas dicas para manter baixo o uso de memória do django.

Os principais pontos:

  • Verifique se o debug está definido como false (você já sabe disso).
  • Use "ServerLimit" na sua configuração do apache
  • Verifique se nenhum objeto grande está sendo carregado na memória
  • Considere servir conteúdo estático em um processo ou servidor separado.
  • Use "MaxRequestsPerChild" na sua configuração do apache
  • Descubra e entenda quanta memória você está usando
Jason Baker
fonte
2
Obrigado, eu já tinha lido aqueles. São os números 3 e 6 nos quais eu esperava mais detalhes! ;-)
Andy Baker
3

Outra vantagem do mod_wsgi: defina um maximum-requestsparâmetro em sua WSGIDaemonProcessdiretiva e o mod_wsgi reiniciará o processo daemon de vez em quando. Não deve haver efeito visível para o usuário, exceto o carregamento lento da página na primeira vez em que um novo processo é atingido, pois ele carregará o Django e o código do aplicativo na memória.

Mas mesmo se você faz tem vazamentos de memória, que deve manter o tamanho do processo de ficar muito grande, sem a necessidade de serviço de interrupção para os usuários.

AdamKG
fonte
1
Algo semelhante é mencionado aqui: mail-archive.com/[email protected]/msg84698.html apenas eles usaram o tempo limite de inatividade em vez de pedidos máximos.
Tomas Andrle
3

Aqui está o script que eu uso para o mod_wsgi (chamado wsgi.py e coloquei a raiz do meu projeto do 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()

Ajuste myproject.settings e o caminho, conforme necessário. Eu redireciono toda a saída para / dev / null, pois mod_wsgi por padrão impede a impressão. Use o registro.

Para o 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>

Espero que isso ajude pelo menos a configurar o mod_wsgi para que você possa ver se faz alguma diferença.

Staale
fonte
1

Caches: verifique se estão sendo lavados. É fácil para algo pousar em um cache, mas nunca ser GC por causa da referência de cache.

Código swig'd: verifique se o gerenciamento de memória está sendo feito corretamente, é muito fácil perdê-los em python, especialmente com bibliotecas de terceiros

Monitoramento: se possível, obtenha dados sobre o uso da memória e ocorrências. Normalmente, você verá uma correlação entre um determinado tipo de solicitação e o uso de memória.

Richard Levasseur
fonte
1

Nos deparamos com um bug no Django com grandes sitemaps (10.000 itens). Parece que o Django está tentando carregar todos eles na memória ao gerar o mapa do site: http://code.djangoproject.com/ticket/11572 - efetivamente mata o processo apache quando o Google faz uma visita ao site.

Emil Stenström
fonte