2012-09-21 14 views
5

Sono completamente confuso sull'uso della memoria di uno specifico script python. Suppongo di non sapere come definire l'utilizzo nonostante advice da diverse domande SO/Answers.Utilizzo memoria in Python: Qual è la differenza tra memory_profiler e guppy?

Le mie domande sono: Qual è la differenza tra memory_profiler e guppy.hpy? Perché uno mi sta dicendo che sto usando enormi quantità di memoria, e l'altro mi sta dicendo che non lo sono?

Sto lavorando con pysam, una libreria per accedere ai file SAM/BAM di bioinformatica. Il mio script principale esaurisce rapidamente la memoria durante la conversione di SAM (ASCII) in BAM (Binary) e la manipolazione dei file in mezzo.

Ho creato un piccolo esempio di test per capire quanta memoria viene allocata in ogni passaggio.

# test_pysam.py: 

import pysam 
#from guppy import hpy 

TESTFILENAME = ('/projectnb/scv/yannpaul/MAR_CEJ082/' + 
       'test.sam') 
#H = hpy() 

@profile # for memory_profiler 
def samopen(filename): 
# H.setrelheap() 
    samf = pysam.Samfile(filename) 
# print H.heap() 
    pass 


if __name__ == "__main__": 
    samopen(TESTFILENAME) 

monitoraggio l'utilizzo della memoria con memory_profiler (python -m memory_profiler test_pysam.py) determina il seguente output:

Filename: test_pysam.py 

Line # Mem usage Increment Line Contents 
================================================ 
    10        @profile # for memory_profiler 
    11        def samopen(filename): 
    12  10.48 MB  0.00 MB # print H.setrelheap() 
    13 539.51 MB 529.03 MB  samf = pysam.Samfile(filename) 
    14        # print H.heap() 
    15 539.51 MB  0.00 MB  pass 

Poi commentando @profile decoratore e decommentando le guppy linee connesse, ottengo il seguente output (python test_pysam.py):

Partition of a set of 3 objects. Total size = 624 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0  1 33  448 72  448 72 types.FrameType 
    1  1 33  88 14  536 86 __builtin__.weakref 
    2  1 33  88 14  624 100 csamtools.Samfile 

La dimensione totale della riga 13 è 529,03 MB in un caso e 624 byte nell'altra. Cosa sta succedendo qui? 'test.sam' è un file SAM da 52 MB (di nuovo un formato ASCII). È un po 'complicato per me scavare in profondità nel pysam, poiché si tratta di un wrapper attorno a una libreria C relativa a samtools. Indipendentemente da cosa sia effettivamente un Samfile, penso che dovrei essere in grado di sapere quanta memoria è allocata per crearlo. Quale procedura devo usare per tracciare correttamente l'utilizzo della memoria di ogni fase del mio programma python più grande e complesso?

+0

Si noti che "test.sam" si trova su una seconda riga perché era un nome molto più lungo e una volta che l'ho modificato mi sono reso conto che le informazioni sul numero di linea sarebbero spente se inserissi il nome del file su una riga. – Yann

risposta

7

Qual è la differenza tra memory_profiler e guppy.hpy?

Capisci la differenza tra la vista interna dell'heap e la vista esterna del sistema operativo del SO? (Per esempio, quando l'interprete Python chiama free su 1MB, questo non immediatamente o forse mai più restituisce 1 milione di pagine al sistema operativo, per molteplici ragioni.) Se lo fai, allora la risposta è abbastanza semplice: memory_profiler sta chiedendo al sistema operativo l'utilizzo della memoria; guppy lo sta capendo internamente dalle strutture dell'heap.

Oltre a ciò, memory_profiler ha un guppy di funzionalità che non esegue automaticamente lo strumenting della funzione per stampare un report dopo ogni riga di codice; è altrimenti molto più semplice e facile ma meno flessibile. Se c'è qualcosa che sai che vuoi fare e memory_profiler sembra non farlo, probabilmente non può; con guppy, forse può, quindi studia i documenti e la fonte.

Perché uno mi sta dicendo che sto usando enormi quantità di memoria e l'altro mi sta dicendo che non lo sono?

È difficile esserne sicuri, ma qui ci sono alcune ipotesi; la risposta è probabilmente una combinazione di più di uno:

Forse samtools usa mmap per mappare file abbastanza piccoli interamente in memoria. Ciò aumenterebbe l'utilizzo della pagina in base alla dimensione del file, ma non aumenterebbe l'utilizzo dell'heap.

Forse samtools o pysam crea un sacco di oggetti temporanei che vengono rapidamente liberati. Potresti avere molta frammentazione (solo un paio di PyObjects in diretta su ogni pagina), o il malloc del tuo sistema potrebbe aver deciso di tenere molti nodi nella sua lista libera a causa del modo in cui ti stai allocando, o potrebbe non avere pagine restituite al sistema operativo ancora, o la macchina virtuale del sistema operativo non può avere pagine recuperate che sono state restituite. La ragione esatta è quasi sempre impossibile da indovinare; la cosa più semplice da fare è assumere che la memoria liberata non venga mai restituita.

Quale procedura devo usare per profilare correttamente l'utilizzo della memoria di ogni fase del mio programma python più grande e complesso?

Se stai chiedendo circa l'utilizzo della memoria da un punto di vista operativo, memory_profiler sta facendo esattamente quello che vuoi. Mentre i principali scavi in ​​pysam possono essere difficili, dovrebbe essere banale racchiudere alcune delle funzioni con il decoratore @profile. Quindi saprai quali funzioni C sono responsabili della memoria; se vuoi scavare più a fondo, devi ovviamente profilare a livello C (a meno che non ci siano informazioni nei documenti samtools o dalla comunità samtools).

+0

Ottima risposta, grazie. – Yann