2010-01-14 12 views
7

Sto analizzando il mio server contorto. Usa molta più memoria di quanto mi aspettassi. Il suo utilizzo della memoria cresce nel tempo.L'utilizzo della memoria segnalato da guppy differisce dal comando ps

ps -o pid,rss,vsz,sz,size,command 
    PID RSS VSZ SZ SZ COMMAND 
7697 70856 102176 25544 88320 twistd -y broadcast.tac 

Come si può vedere che costa 102176 KBs, vale a dire, 99,78,125 mila MBs. E io uso guppy da un tombino contorto per guardare il profilo di utilizzo della memoria.

>>> hp.heap() 
Partition of a set of 120537 objects. Total size = 10096636 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 61145 51 5309736 53 5309736 53 str 
    1 27139 23 1031596 10 6341332 63 tuple 
    2 2138 2 541328 5 6882660 68 dict (no owner) 
    3 7190 6 488920 5 7371580 73 types.CodeType 
    4 325 0 436264 4 7807844 77 dict of module 
    5 7272 6 407232 4 8215076 81 function 
    6 574 0 305776 3 8520852 84 dict of class 
    7 605 1 263432 3 8784284 87 type 
    8 602 0 237200 2 9021484 89 dict of type 
    9 303 0 157560 2 9179044 91 dict of zope.interface.interface.Method 
<384 more rows. Type e.g. '_.more' to view.> 

Hum ... Sembra che ci sia qualcosa che non va. Guppy mostra che l'utilizzo totale della memoria è 10096636 byte, ovvero 9859.996 KB o 9.628 MB.

Questa è un'enorme differenza. Cosa c'è che non va in questo strano risultato? Che cosa sto facendo di sbagliato?

Aggiornamento: Ieri sera ho scritto uno script di monitoraggio. Registra l'utilizzo della memoria e il numero di utenti on-line. È un server radio, quindi puoi vedere che ci sono le radio e gli ascoltatori totali. Ecco la figura che ho generato da matplotlib. alt text http://static.ez2learn.com/temp/mem_figure.svg

Qualcosa è strano. A volte l'utilizzo della memoria stampato da ps è molto basso, come questo

2010-01-15 00:46:05,139 INFO 4 4 17904 36732 9183 25944 
2010-01-15 00:47:03,967 INFO 4 4 17916 36732 9183 25944 
2010-01-15 00:48:04,373 INFO 4 4 17916 36732 9183 25944 
2010-01-15 00:49:04,379 INFO 4 4 17916 36732 9183 25944 
2010-01-15 00:50:02,989 INFO 4 4 3700 5256 1314 2260 

Qual è la ragione del valore super basso di utilizzo della memoria? E per di più, anche se non ci sono radio online, nessun ascoltatore, l'utilizzo della memoria è ancora alto.

risposta

6

possibilmente dovuto scambiare/prenotazione memoria, sulla base di definizione di ps:

RSS: resident set size, the non-swapped physical memory 
    that a task has used (in kiloBytes). 

VSZ: virtual memory usage of entire process. 
    vm_lib + vm_exe + vm_data + vm_stack 

può essere un po 'di confusione, 4 diverse metriche dimensioni possono essere visti con:

# ps -eo pid,vsz,rss,sz,size,cmd|egrep python 

PID VSZ RSS SZ SZ CMD 
23801 4920 2896 1230 1100 python 

la dimensione virtuale include la memoria che è stata riservata dal processo e non utilizzata, la dimensione di tutte le librerie condivise che sono state caricate, le pagine che sono state scambiate e i blocchi che erano già stati liberati dal processo, quindi potrebbe essere molto più grande della dimensione di tutti i live oggetti in python.

alcuni strumenti aggiuntivi per indagare le prestazioni della memoria:

buona guida sul rintracciare le perdite di memoria in Python utilizzando PPB e objgraph:

http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks

+0

Ma anche io confronto 69 MB con 10 MB, è troppo lontano. Quale potrebbe essere il problema? E per di più, l'utilizzo della memoria cresce con il tempo. All'inizio, l'RSS è di circa 2xMB, e arriva a 6x ora. –

+0

alcuni degli oggetti segnalati da guppy potrebbero essere scambiati in modo che Python possa riportarli, mentre rss non lo includerà. Non sono sicuro perché il processo riservi così tanta memoria, forse tonnellate di librerie condivise ..? – jspcal

+0

Tutte le librerie sono caricate all'avvio. Utilizza solo 2x MB nel campo RSS all'avvio del server. Non ha senso che le librerie occupino un utilizzo extra della memoria. C'è un modo per sapere qual è l'utilizzo della memoria invisibile? –

3

Come sottolineato in precedenza la dimensione RSS è quello che siete più interessati a qui.La dimensione "virtuale" include le librerie mappate, che probabilmente non vuoi contare.

È passato un po 'di tempo da quando ho usato un po' di memoria, ma sono abbastanza sicuro che le statistiche che stampa non includano l'overhead aggiunto da heapy stesso. Questo overhead può essere piuttosto significativo (ho visto un processo RSS di 100MB crescere un'altra dozzina di MB, vedi http://www.pkgcore.org/trac/pkgcore/doc/dev-notes/heapy.rst).

Ma nel tuo caso sospetto che il problema sia che stai usando una libreria C che perde o usa la memoria in un modo che non tiene traccia. Heapy è consapevole della memoria utilizzata direttamente dagli oggetti python, ma se quegli oggetti racchiudono gli oggetti C allocati separatamente, heapy non è in genere a conoscenza di quella memoria. Potresti essere in grado di aggiungere un ampio supporto ai tuoi binding (ma se non controlli i binding che usi è ovviamente una seccatura, e anche se controlli i binding potresti non essere in grado di farlo a seconda di cosa stai avvolgendo).

Se ci sono perdite a livello C, anche l'heap perde la traccia di quella memoria (le dimensioni RSS aumenteranno, ma le dimensioni segnalate di heapy rimarranno invariate). Valgrind è probabilmente la soluzione migliore per rintracciarli, proprio come nelle altre applicazioni C.

Infine: la frammentazione della memoria spesso causa l'utilizzo della memoria (come mostrato in alto) per salire ma non verso il basso (molto). Questo di solito non è un grosso problema con i daemon, dal momento che il processo riutilizzerà questa memoria, non è appena rilasciato al sistema operativo, quindi i valori in alto non tornano indietro. Se l'utilizzo della memoria (come visto in alto) sale più o meno linearmente con il numero di utenti (connessioni), non torna indietro, ma non continua a crescere per sempre fino a quando non raggiungi un nuovo numero massimo di utenti, probabilmente la frammentazione incolpare.

1

Questa non è una risposta completa, ma dal tuo passo d'uomo, suggerirei di eseguire manualmente gc.collect() prima di cercare con ps o top. guppy mostrerà l'heap allocato, ma non farà nulla per liberare proattivamente oggetti che non sono più assegnati.

Problemi correlati