Python中GC的使用
一、python的垃圾回收机制
引用计数为主,分代回收为辅
引用计数:python中一切皆为对象,核心是一个结构体PyObject其中维护了一个int型变量ob_refcnt。
当对象有新的引用时候ob_refcnt就会增加1,同理删除就会减少。其中还有小整数对象池,大整数对象池等概念。此处就不在记录
但此时会有一个十分严重的问题就是循环引用无法回收
什么是循环引用呢,就是 如果⼀个数据结构引⽤了它⾃身, 即如果这个数据结构是⼀个循环数据结构, 那么某些引⽤计数值是肯定⽆法变成零的。比如循环链表,此处举一个简单的例子
class ClassA(): def __init__(self): print('Object born,id:%s'%str(hex(id(self)))) def f2(): while True: c1=ClassA() c2=ClassA() c1.t=c2 c2.t=c1 del c1 del c2 f2()
在执行del c1和c2时候,由于c1有指向c2的引用,c2有指向c1的引用。del之后两者引用数只会减少到1,并不会被回收。
二、隔代回收
在python程序内部每创建一个对象,就会将对象分到一代中,每个代就是一个链表,代进行标记-清除的时间 与 代内对象存活时间成正比例关系。
当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数,当两者的差值高于某个阈值时就触发GC回收机制。具体怎么排查,将0代放到1代,我也不知道。还有就只分配对象和取消分配对象怎么理解?有人知道么???
另外还有两种情况下会触发GC机制:2、调用gc.collect() 3、程序退出
三、获取对象的引用计数
import sys a=[1,2,3] getrefcount(a) Out[4]: 2 #之所以是2是因为a作为参数传给了getrefcount
四、对gc使用的介绍
<1>、gc.collect([generation]) 显式进⾏垃圾回收, 可以输⼊参数, 0代表只检查第⼀代的对象, 1代表检查⼀, ⼆代的对象, 2代表检查⼀, ⼆, 三代的对象, 如果不传参数, 执⾏⼀个full collection, 也就是等于传2。
<2>、 gc.get_threshold() 获取的gc模块中⾃动执⾏垃圾回收的频率返回阀值!
<3>、 gc.set_threshold(threshold0[, threshold1[, threshold2]) 设置阀值。
<4>、 gc.get_count() :Return the current collection counts as a tuple of (count0, count1, count2).