python之gc垃圾回收

gc 回收机制

gc 主要由以下3个部分组成

  1. 引用计数
  2. 标记-删除
  3. 分代回收

引用计数

对象的引用计数可以通过 sys.getrefcount(object)得到

引用数指的是对象被引用的次数,一般通过创建变量,变量绑定来增加,

a = 1000
sys.getrefcount(a) -> 2 
###注意:sys.getrefcount(a)得到的是对象的引用计数,即变量a所指向的内存地址的值1000被引用的次数,这里得到2是因为
a=1000时引用了1次 而sys.getrefcont(a)时又引用了一次

b = a
sys.getrefcount(a) -> 3

del a
sys.getrefcount(a) -> 2

id(b) -> 3097439675248
del b

c = 1001
id(c) -> 3097439675248

###这里大家可以发现c与b之前的所指向的内存地址是同一个,这是因为在大部分情况下当1个内存地址引用计数为0时,python
###内部就会马上把这个内存地址回收,标记为可用地址,在下次请求地址时分发出去

标记-删除

引用计数不是万能的,在一些特定的情况下,即使对象指向为空,但是引用计数并不为0

list1 = []
list2 = []
list1.append(list2)
list2.append(list1)

sys.getrefcount(list1) -> 3
sys.getrefcount(list2) -> 3
###这时候 del list1,list2 只会使它们的引用计数减1
del list1,list2

这时候list1,list2的内存并不会得到释放,直到python的回收计数达到阀值触发了回收机制,然后python内部会遍历所有对象,把被正确引用的对象作标记保留
而没有正确引用的对象则进行回收,释放内存
gc.get_count() 查看当前回收计数
gc.get_threshold() 查看回收阈值  默认为 (700,10,10) 分别对应一、二、三代回收阀值

分代回收

而上述被标记的对象会被保存到二代对象当中,回收计数中的第二位会+1,
触发一代回收阀值时会检查新建对象,把被正确引用的对象作标记保留而没有正确引用的对象则进行回收,释放内存,存活对象保存到二代对象当中,二代回收计数+1
触发二代回收阀值时会检查新建对象与二代对象并回收,存活的对象被保存到三代对象中,三代回收计数+1
触发三代回收阀值时会检查新建对象与二代对象与三代对象,计数器清0
如此循环直至程序结束,所以Python程序占用的空间不会特别大,但是同时因为gc机制一直在后台运行各种操作,会在一定的程度上降低程序的效率.

posted on 2018-06-05 11:00  Dear、  阅读(175)  评论(0编辑  收藏  举报

导航