2012-09-21 4 views
5

Estoy completamente confundido sobre el uso de memoria de un script python específico. Supongo que realmente no sé cómo perfilar el uso a pesar de advice de varias SO Questions/Answers.Uso de la memoria en Python: ¿Cuál es la diferencia entre memory_profiler y guppy?

Mis preguntas son: ¿Cuál es la diferencia entre memory_profiler y guppy.hpy? ¿Por qué uno me dice que estoy usando una gran cantidad de memoria y el otro me está diciendo que no?

Estoy trabajando con pysam, una biblioteca para acceder a los archivos SAM/BAM bioinformáticos. Mi script principal se está quedando sin memoria rápidamente al convertir SAM (ASCII) a BAM (Binario) y manipular los archivos intermedios.

Creé un pequeño ejemplo de prueba para comprender cuánta memoria se asigna en cada paso.

# 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) 

Supervisión del uso de la memoria con memory_profiler (python -m memory_profiler test_pysam.py) da como resultado el siguiente resultado:

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 

Entonces comentando @profile decorador y eliminando el comentario de los guppy líneas relacionadas, me sale el siguiente resultado (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 

El tamaño total de la línea 13 es de 529.03 MB en un caso y 624 bytes en el otro. ¿Qué está pasando realmente aquí? 'test.sam' es un archivo ~ 52MB SAM (de nuevo un formato ASCII). Es un poco complicado para mí profundizar en pysam, ya que es un contenedor de una biblioteca de C relacionada con samtools. Independientemente de lo que realmente sea un Samfile, creo que debería ser capaz de aprender cuánta memoria se asigna para crearlo. ¿Qué procedimiento debo usar para perfilar correctamente el uso de la memoria de cada paso de mi programa python más grande y complejo?

+0

Tenga en cuenta que 'test.sam' está en una segunda línea porque era un nombre mucho más largo y una vez que lo cambié me di cuenta de que la información de mi número de línea estaría desactivada si pongo el nombre de archivo en una línea. – Yann

Respuesta

7

¿Cuál es la diferencia entre memory_profiler y guppy.hpy?

¿Entiende la diferencia entre su vista interna del montón y la vista externa del programa de su sistema operativo? (Por ejemplo, cuando el intérprete de Python llama al free en 1MB, eso no devuelve inmediatamente, o quizás nunca, 1MB de páginas al sistema operativo, por varias razones). Si lo hace, la respuesta es bastante fácil: memory_profiler está pidiendo al sistema operativo su uso de memoria; guppy está averiguando internamente desde las estructuras de montón.

Más allá de eso, memory_profiler tiene una función que guppy doesn't-instrumenting automáticamente su función para imprimir un informe después de cada línea de código; de lo contrario es mucho más simple y fácil pero menos flexible. Si hay algo que sabes que quieres hacer y memory_profiler no parece hacerlo, probablemente no pueda hacerlo; con guppy, tal vez sí, así que estudia los documentos y la fuente.

¿Por qué me dicen que estoy usando una gran cantidad de memoria y el otro me dice que no?

Es difícil estar seguro, pero aquí hay algunas conjeturas; la respuesta es probable que sea una combinación de más de uno:

Quizás samtools use mmap para asignar archivos lo suficientemente pequeños en la memoria. Esto aumentaría el uso de su página por el tamaño del archivo, pero no aumentaría el uso de su pila.

Tal vez samtools o pysam crea una gran cantidad de objetos temporales que se liberan rápidamente. Podría tener mucha fragmentación (solo un par de PyObjects en vivo en cada página), o malloc de su sistema podría haber decidido que debería mantener muchos nodos en su lista de publicaciones debido a la forma en que ha estado asignando, o puede que no haya devuelto páginas. al sistema operativo aún, o la VM del sistema operativo puede no haber recuperado las páginas que se devolvieron. La razón exacta es casi siempre imposible de adivinar; lo más simple es suponer que nunca se devuelve la memoria liberada.

¿Qué procedimiento debo usar para perfilar correctamente el uso de memoria de cada paso de mi programa python más grande y complejo?

Si está preguntando sobre el uso de memoria desde el punto de vista del sistema operativo, memory_profiler está haciendo exactamente lo que desea. Si bien puede ser difícil profundizar en pysam, sería trivial ajustar algunas de las funciones con el decorador @profile. Entonces sabrá qué funciones C son responsables de la memoria; si quieres profundizar más, obviamente tienes que crear un perfil en el nivel C (a menos que haya información en los documentos samtools o de la comunidad samtools).

+0

Excelente respuesta, gracias. – Yann

Cuestiones relacionadas