2013-01-09 7 views
10

Ho un server web django in esecuzione su uwsgi che sembra perdere memoria.Perdita di memoria per python non-object perturbante

In particolare, l'RSS dei processi cresce lentamente fino a quando non è necessario riavviarlo.

Sono a conoscenza delle altre domande simili a questo, tuttavia tutte le soluzioni/conclusioni trovate finora non sembrano applicabili (che io possa trovare) in questo caso.

Finora, ho usato meliae, Heapy, pympler e objgraph per ispezionare il mucchio di pitone e tutti riferire la stessa cosa: Un mucchio cercando normale utilizzando circa 40MB di memoria (atteso) con pochissimo varianza nel tempo (come desiderato).

Questo è sfortunatamente del tutto incoerente con il processo RSS, che crescerà volentieri a 400MB + con no riflesso nella dimensione dell'heap python.

Un esempio di output per illustrare il mio punto -

uscita Pympler confrontando python heap/memoria oggetto vs processo RSS:

Memory snapshot: 
             types | # objects | total size 
============================================= | =========== | ============ 
             dict |  20868 |  19852512 
              str |  118598 |  11735239 
             unicode |  19038 |  10200248 
             tuple |  58718 |  5032528 
             type |  1903 |  1720312 
             code |  13225 |  1587000 
             list |  11393 |  1289704 
          datetime.datetime |  6953 |  333744 
              int |  12615 |  302760 
    <class 'django.utils.safestring.SafeUnicode |   18 |  258844 
             weakref |  2908 |  255904 
    <class 'django.db.models.base.ModelState |  3172 |  203008 
        builtin_function_or_method |  2612 |  188064 
         function (__wrapper__) |  1469 |  176280 
             cell |  2997 |  167832 
          getset_descriptor |  2106 |  151632 
          wrapper_descriptor |  1831 |  146480 
              set |   226 |  143056 
             StgDict |   217 |  138328 
--------------------------- 
Total object memory: 56189 kB 
Total process usage: 
- Peak virtual memory size: 549016 kB 
- Virtual memory size: 549012 kB 
- Locked memory size: 0 kB 
- Peak resident set size: 258876 kB 
- Resident set size: 258868 kB 
- Size of data segment: 243124 kB 
- Size of stack segment: 324 kB 
- Size of code segment: 396 kB 
- Shared library code size: 57576 kB 
- Page table entries size: 1028 kB 
--------------------------- 

uscita Heapy che mostra una cosa simile

Memory snapshot: 
Partition of a set of 289509 objects. Total size = 44189136 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 128384 44 12557528 28 12557528 28 str 
    1 61545 21 5238528 12 17796056 40 tuple 
    2 5947 2 3455896 8 21251952 48 unicode 
    3 3618 1 3033264 7 24285216 55 dict (no owner) 
    4 990 0 2570448 6 26855664 61 dict of module 
    5 2165 1 1951496 4 28807160 65 type 
    6 16067 6 1928040 4 30735200 70 function 
    7 2163 1 1764168 4 32499368 74 dict of type 
    8 14290 5 1714800 4 34214168 77 types.CodeType 
    9 10294 4 1542960 3 35757128 81 list 
<1046 more rows. Type e.g. '_.more' to view.> 
--------------------------- 
Total process usage: 
- Peak virtual memory size: 503132 kB 
- Virtual memory size: 503128 kB 
- Locked memory size: 0 kB 
- Peak resident set size: 208580 kB 
- Resident set size: 208576 kB 
- Size of data segment: 192668 kB 
- Size of stack segment: 324 kB 
- Size of code segment: 396 kB 
- Shared library code size: 57740 kB 
- Page table entries size: 940 kB 
--------------------------- 

Si noti che in entrambi i casi, la dimensione dell'heap riportata è 40-50 MB, w mentre il processo RSS è 200MB +.

Ho anche usato get_leaking_objects di objgraph() per tentare di vedere se un C-estensione sta facendo male ref-conteggio, tuttavia il numero di oggetti non gc'able non crescerà notevolmente nel corso del tempo.

Qualcuno ha qualche idea su come eseguire il debug di questo? A questo punto, sto presumendo una delle due cose è il caso:

  • Ho un ricordo C-estensione perdite internamente
  • uwsgi stessa è che perde la memoria (anche se posso trovare altra prova di questo sul net)

Vale la pena ricordare che non ho avuto successo nella replica di questo in qualsiasi tipo di ambiente di sviluppo (anche se è possibile che io non stia facendo abbastanza traffico a loro).

Usiamo un gruppo di moduli che hanno estensioni C (simplejson, hiredis, ecc.) Quindi è sicuramente credibile che potrebbero essere la causa.

Alla ricerca di approcci da adottare per rintracciare questo.

+0

hai settings.py DEBUG = Falso, giusto? – monkut

+0

Sì, ma bella domanda :) – fenn

+0

Mi stavo chiedendo se alla fine hai risolto questo problema? Stiamo riscontrando problemi simili che sono stati riscontrati solo dal passaggio a uwsgi. – Geekfish

risposta

2

Quale versione di Python stai usando? In Python la memoria 2.4 non è stata restituita al sistema operativo dall'allocatore di memoria Python.

Ancora nelle versioni più recenti è possibile vedere un problema correlato all'allocatore di memoria di Python che mantiene elenchi di tipi semplici liberati o nel caso in cui si esegua su Linux un problema intrinseco a come l'implementazione malloc di glibc alloca memoria dal sistema operativo. Dai un'occhiata a http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm e http://pushingtheweb.com/2010/06/python-and-tcmalloc/.

+0

Python 2.6 (nativo di Ubuntu 10.04) nel nostro caso. Analizzerò il problema di malloc, non l'avevo ancora incontrato. – fenn