Riduzione dell'utilizzo della memoria di Django. Frutta bassa appesa?


136

Il mio utilizzo della memoria aumenta nel tempo e il riavvio di Django non è gentile con gli utenti.

Non sono sicuro di come profilare l'utilizzo della memoria, ma alcuni suggerimenti su come iniziare la misurazione sarebbero utili.

Ho la sensazione che ci siano alcuni semplici passaggi che potrebbero produrre grandi guadagni. Garantire che "debug" sia impostato su "False" è evidente.

Qualcuno può suggerire gli altri? Quanto miglioramento sarebbe la memorizzazione nella cache su siti a basso traffico?

In questo caso sto correndo sotto Apache 2.x con mod_python. Ho sentito che mod_wsgi è un po 'più snello, ma sarebbe difficile passare a questo punto se non so che i guadagni sarebbero significativi.

Modifica: grazie per i suggerimenti finora. Qualche suggerimento su come scoprire cosa sta esaurendo la memoria? Esistono guide alla profilazione della memoria di Python?

Inoltre, come detto, ci sono alcune cose che rendono difficile passare a mod_wsgi, quindi mi piacerebbe avere un'idea dei guadagni che potrei aspettarmi prima di andare avanti in quella direzione.

Modifica: Carl ha pubblicato qui una risposta un po 'più dettagliata che vale la pena leggere: Distribuzione di Django: tagliare le spese generali di Apache

Modifica: l'articolo di Graham Dumpleton è il migliore che ho trovato su cose relative a MPM e mod_wsgi. Sono piuttosto deluso dal fatto che nessuno possa fornire informazioni sul debug dell'utilizzo della memoria nell'app stessa.

Modifica finale: Beh, ne ho discusso con Webfaction per vedere se potevano aiutare a ricompilare Apache e questa è la loro parola sull'argomento:

"Non credo davvero che otterrai un grande vantaggio passando a una configurazione MPM Worker + mod_wsgi. Stimo che potresti essere in grado di risparmiare circa 20 MB, ma probabilmente non molto di più."

Così! Questo mi riporta alla mia domanda originale (di cui non sono ancora più saggio). Come si fa a identificare dove si trovano i problemi? È una massima ben nota che non si ottimizza senza test per vedere dove è necessario ottimizzare, ma c'è ben poco in termini di tutorial sulla misurazione dell'utilizzo della memoria di Python e niente di tutto specifico per Django.

Grazie per l'assistenza di tutti, ma penso che questa domanda sia ancora aperta!

Un'altra modifica finale ;-)

L'ho chiesto nella lista degli utenti di django e ho ricevuto delle risposte molto utili

Onestamente l'ultimo aggiornamento di sempre!

Questo è stato appena rilasciato. Potrebbe essere la soluzione migliore in assoluto: profilare le dimensioni degli oggetti Django e l'utilizzo della memoria con Pympler

Risposte:


50

Assicurati di non mantenere riferimenti globali ai dati. Ciò impedisce al garbage collector di Python di rilasciare la memoria.

Non usare mod_python. Carica un interprete all'interno di apache. Se devi usare apache, usa mod_wsgiinvece. Non è difficile cambiare. È molto facile. mod_wsgiè molto più facile da configurare per django che da morto nel cervello mod_python.

Se riesci a rimuovere apache dai tuoi requisiti, sarebbe ancora meglio per la tua memoria. spawningsembra essere il nuovo modo scalabile veloce per eseguire applicazioni Web Python.

EDIT : Non vedo come passare a mod_wsgi potrebbe essere " complicato ". Dovrebbe essere un compito molto semplice. Si prega di approfondire il problema riscontrato con l'interruttore.


4
@Josh: il gonfiore e l'utilizzo della memoria di apache sono stupidi se non stai utilizzando le funzionalità solo di apache. È solo uno strato inutile.
nosklo,

3
Django sostiene ancora mod_python perché mod_wsgi è ancora abbastanza nuovo e vogliono essere conservatori. Ma se segui la community di Django vedrai le persone passare a mod_wsgi in massa. Non ci vorrà molto prima che sia l'opzione consigliata.
Carl Meyer,

1
@Tiago: apache è buono quando hai già molti host virtuali di apache già in atto, usando già SSL con apache, ecc. In questo caso, usa mod_wsgi. Se stai ricominciando da capo, usa spawning. MAI utilizzare mod_python.
nosklo,

1
Grazie, nosklo. Sto dando un'occhiata alla deposizione delle uova .. sembra che abbia poca o nessuna documentazione .. Proverò a seguire alcune istruzioni che ho trovato nei post del blog e vedere dove posso trovare.
Tiago,

1
Hmm, visto che qualcuno ha appena iniziato a usare Django, terrò presente che dovrei usare mod_wsgi.
Powerlord,

28

Se stai utilizzando mod_wsgi e presumibilmente si genera dal momento che è conforme a WSGI, puoi usare Dozer per esaminare l'utilizzo della memoria.

Sotto mod_wsgi basta aggiungere questo in fondo allo script WSGI:

from dozer import Dozer
application = Dozer(application)

Quindi punta il tuo browser su http: // domain / _dozer / index per vedere un elenco di tutte le allocazioni di memoria.

Aggiungerò anche la mia voce di supporto per mod_wsgi. Fa un mondo di differenza in termini di prestazioni e utilizzo della memoria rispetto a mod_python. Il supporto di Graham Dumpleton per mod_wsgi è eccezionale, sia in termini di sviluppo attivo sia nell'aiutare le persone nella mailing list a ottimizzare le loro installazioni. David Cramer su curse.com ha pubblicato alcuni grafici (che non riesco a trovare ora sfortunatamente) che mostrano la drastica riduzione dell'uso della CPU e della memoria dopo essere passati a mod_wsgi su quel sito ad alto traffico. Molti degli sviluppatori di django sono passati. Scherzi a parte, è un gioco da ragazzi :)


Nel qual caso presto pubblicherò una domanda che chiede come si ottiene l'autenticazione basata su cookie per gli utenti di django che accedono ai file statici ...
Andy Baker,

15

Queste sono le soluzioni di profiler di memoria Python di cui sono a conoscenza (non relative a Django):

Disclaimer: ho una partecipazione in quest'ultimo.

La documentazione del singolo progetto dovrebbe darti un'idea di come usare questi strumenti per analizzare il comportamento della memoria delle applicazioni Python.

Quella che segue è una bella "storia di guerra" che fornisce anche alcuni suggerimenti utili:


5

Inoltre, controlla se non usi nessuno dei leaker conosciuti. MySQLdb è noto per perdere enormi quantità di memoria con Django a causa di bug nella gestione di unicode. Oltre a ciò, Django Debug Toolbar potrebbe aiutarti a rintracciare i maiali.


amix.dk/blog/viewEntry/19420 mostra che il bulldozer viene utilizzato per mostrare che MySQLdb stava perdendo memoria. MySQLdb 1.2.3c1 e versioni successive risolve questo problema.
msanders,

Come potrebbe django-debug-toolbaraiutare?
Wtower,

4

Oltre a non mantenere i riferimenti globali a oggetti di dati di grandi dimensioni, cerca di evitare di caricare insiemi di dati di grandi dimensioni in memoria, ove possibile.

Passa a mod_wsgi in modalità demone e usa il mpm worker di Apache invece di prefork. Quest'ultimo passaggio può consentire di servire molti più utenti simultanei con un sovraccarico di memoria molto inferiore.


Vedi anche la risposta di Carl qui: stackoverflow.com/questions/488864/…
Andy Baker,

Inoltre - in alcuni post che ho letto sembra che il vero vantaggio sia passare al lavoratore MPM piuttosto che usare mod_wsgi ...
Andy Baker

4

Webfaction in realtà ha alcuni suggerimenti per mantenere basso l'uso della memoria di django.

I punti principali:

  • Assicurati che il debug sia impostato su false (lo sai già).
  • Usa "ServerLimit" nella tua configurazione di apache
  • Verificare che non vengano caricati oggetti di grandi dimensioni in memoria
  • Valuta la possibilità di offrire contenuto statico in un processo o server separato.
  • Usa "MaxRequestsPerChild" nella tua configurazione di apache
  • Scopri e comprendi quanta memoria stai utilizzando

2
Grazie, avevo già letto quelli. Sono i numeri 3 e 6 che speravo in qualche dettaglio in più! ;-)
Andy Baker,

3

Un altro vantaggio per mod_wsgi: impostare un maximum-requestsparametro nella WSGIDaemonProcessdirettiva e mod_wsgi riavvierà il processo daemon ogni tanto. Non ci dovrebbero essere effetti visibili per l'utente, a parte un caricamento lento della pagina la prima volta che viene avviato un nuovo processo, poiché caricherà Django e il codice dell'applicazione in memoria.

Ma anche se si fare avere perdite di memoria, che dovrebbe mantenere le dimensioni processo di diventare troppo grande, senza dover interrompere il servizio agli utenti.


1
Qualcosa di simile è menzionato qui: mail-archive.com/django-users@googlegroups.com/msg84698.html solo loro hanno usato il timeout di inattività anziché le richieste massime.
Tomas Andrle,

3

Ecco lo script che uso per mod_wsgi (chiamato wsgi.py, e metto il root nel mio progetto 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()

Regola myproject.settings e il percorso secondo necessità. Reindirizzo tutto l'output a / dev / null poiché mod_wsgi per impostazione predefinita impedisce la stampa. Utilizzare invece la registrazione.

Per 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>

Spero che questo dovrebbe almeno aiutarti a configurare mod_wsgi in modo da poter vedere se fa la differenza.


1

Cache: assicurati che vengano svuotate. È facile per qualcosa atterrare in una cache, ma mai essere GC'd a causa del riferimento alla cache.

Codice Swig'd: assicurati che qualsiasi gestione della memoria sia eseguita correttamente, è davvero facile perderli in Python, specialmente con librerie di terze parti

Monitoraggio: se possibile, ottenere dati sull'utilizzo della memoria e sui risultati. Di solito vedrai una correlazione tra un certo tipo di richiesta e l'utilizzo della memoria.


1

Ci siamo imbattuti in un bug in Django con grandi sitemap (10.000 articoli). Sembra che Django stia cercando di caricarli tutti in memoria durante la generazione della sitemap: http://code.djangoproject.com/ticket/11572 - uccide efficacemente il processo di apache quando Google visita il sito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.