2012-09-21 109 views
5

我对特定python脚本的内存使用情况感到十分困惑。尽管advice来自几个SO Questions/Answers,但我想我真的不知道如何剖析使用情况。Python中的内存使用情况:memory_profiler和guppy之间有什么区别?

我的问题是:memory_profilerguppy.hpy有什么区别?为什么一个人告诉我我正在使用大量的记忆,另一个告诉我我不是?

我正在与pysam合作,这是一个用于访问生物信息学SAM/BAM文件的库。将SAM(ASCII)转换为BAM(二进制)并处理它们之间的文件时,我的主脚本快速耗尽内存。

我创建了一个小测试示例来了解在每个步骤中分配了多少内存。

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

监测与memory_profiler(python -m memory_profiler test_pysam.py)的结果在下面的输出内存使用情况:

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 

然后注释掉@profile装饰和取消注释guppy相关的线,我得到下面的输出(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 

第13行的总大小为529.03 MB在一个案例中另一个是624字节。这里究竟发生了什么? 'test.sam'是一个〜52MB的SAM(同样是一个ASCII格式)文件。对我来说,深入探究pysam有点棘手,因为它是一个与samtools相关的C库的封装。不管实际是什么,我认为我应该能够学习分配多少内存来创建它。我应该使用什么过程来正确分析我的更大,更复杂的python程序的每一步的内存使用情况?

+0

请注意'test.sam'在第二行,因为它是一个更长的名称,一旦我改变它,我意识到我的行号信息将关闭,如果我把文件名放在一行上。 – Yann

回答

7

memory_profiler和guppy.hpy有什么区别?

您是否理解内部堆视图与操作系统外部视图之间的区别? (例如,当Python解释器在1MB上调用free时,由于多种原因,它不会立即(或甚至可能)返回1MB的页面到操作系统。)如果这样做,那么答案很简单:memory_profiler要求OS使用内存;孔雀从堆结构内部找出它。

除此之外,memory_profiler有一个功能,guppy不会自动检测你的函数在每行代码后打印报表;否则它会更简单,更简单但不够灵活。如果你知道你想要做的事情,而memory_profiler似乎没有这样做,它可能不会;与孔布,也许它可以,所以研究文档和来源。

为什么一个人告诉我我正在使用大量的内存,另一个告诉我我不是?

这很难确定,但这里有一些猜测;答案很可能是多个组合:

也许samtools使用mmap将足够小的文件映射到内存中。这会使您的页面使用量增加文件大小,但不会增加您的堆使用率。

也许samtools或pysam会创建很多快速释放的临时对象。你可能有很多碎片(每个页面上只有一对活着的PyObjects),或者你的系统的malloc可能已经决定它应该保留很多节点在它的freelist中,因为你已经分配了它的方式,或者它可能没有返回页面到操作系统,或者操作系统的虚拟机可能没有回收返回的页面。确切的原因几乎总是不可能猜到;最简单的做法是假定释放的内存永远不会返回。

我应该使用什么程序来正确分析我的更大,更复杂的python程序的每个步骤的内存使用情况?

如果您从操作系统的角度询问内存使用情况,memory_profiler正在按照您的要求进行操作。虽然主要深入pysam可能很困难,但用装饰器包装几个功能应该是微不足道的。然后你会知道哪些C函数负责内存;如果你想深入挖掘,你显然必须在C级别进行配置(除非有samtools文档或samtools社区的信息)。

+0

很好的答案,谢谢。 – Yann

相关问题