python垃圾回收与内存泄露

Python垃圾回收

Python垃圾回收的工作原理是:为每个内存对象维护一个引用计数,当对象的引用计数为零时解释器会自动释放内存。

在Python中,有2中方式可以触发垃圾回收:一种方式是用户显示调用gc.collect(),另一种方式是每次Python为新对象分配内存时,检查threshold阀值,当对象数量超过threshold设置的阀值就开始进行垃圾回收。但是Python垃圾回收频频触发会影响程序执行的性能

优化前:频繁做无用垃圾回收

[root@xiaoxiong gc]# cat 2.py 
data = range(1,4000000)   
wdict = dict(zip(data,data))  
[root@xiaoxiong gc]# time python 2.py
real    0m17.551s
user    0m17.123s
sys     0m0.420s
[root@xiaoxiong gc]# 


优化后的垃圾回收程序


[root@xiaoxiong gc]# cat 1.py 
import gc   
gc.disable()   
data = range(1,5000000)   
wdict = dict(zip(data,data))   
gc.enable()  
[root@xiaoxiong gc]# 
[root@xiaoxiong gc]# 
[root@xiaoxiong gc]# time python 1.py
real    0m2.596s
user    0m2.068s
sys     0m0.513s
[root@xiaoxiong gc]# 


优化前的程序无法释放部分内存,而垃圾回收程序却在做无用功,程序的执行性能将大打折扣。调优后在程序片段运行的这段时间内禁止进行垃圾回收,程序性能大为提高。

Python内存泄露

Python虽然能自动垃圾回收,但是如果使用不当,也会造成内存泄露,造成这种现象的原因一般都是由于某些对象引用了自身,造成了类似的一个引用循环。

下面的程序提供了更多的信息来帮助定位泄露发生地点的办法。

[root@xiaoxiong cb8]# 
[root@xiaoxiong cb8]# cat 1.py 
import gc, time
def dump_garbage():
    """ show us what the garbage is about """
    # Force collection
    print "\nGARBAGE:"
    gc.collect()
    print "\nGARBAGE OBJECTS:"
    for x in gc.garbage:
        print 'hello'
        s = str(x)
        #if len(s) > 80: s = s[:77]+'...'
        print type(x),"\n  ", s
        
class Obj:  
    def __init__(self,name='A'):  
        self.name = name  
        print '%s inited' % self.name  
    def __del__(self):  
        print '%s deleted' % self.name  
        
def hello():
    dump_garbage()
        
if __name__=="__main__":
    gc.enable()
    gc.set_debug(gc.DEBUG_LEAK)
    # Simulate a leak (a list referring to itself) and show it
    
    a = Obj('A')  
    b = Obj('B')  
    c = Obj('c')  
  
    c.attrObj = b  
    b.attrObj = c     
    
    del a
    del b
    del c
    
[root@xiaoxiong cb8]# python 1.py 
A inited
B inited
c inited
A deleted
GARBAGE:
gc: uncollectable 
gc: uncollectable 
gc: uncollectable 
gc: uncollectable 
GARBAGE OBJECTS:
hello
 
   <__main__.Obj instance at 0x7f59410c9ea8>
hello
 
   <__main__.Obj instance at 0x7f59410c9dd0>
hello
 
   {'name': 'B', 'attrObj': <__main__.Obj instance at 0x7f59410c9dd0>}
hello
 
   {'name': 'c', 'attrObj': <__main__.Obj instance at 0x7f59410c9ea8>}
[root@xiaoxiong cb8]# 

该程序第一步调用gc.set_debug,通知gc模块将泄露的对象放入gc.garbage列表中,而不是将它们回收利用。然后dump_garbage函数调用gc.collect来强制回收进程的运行,即使当前内存还很充裕,这样它就可以检查gc.garbage中的每一项并打印出类型和内容。

你可能感兴趣的:(编程语言,python)