Python 垃圾回收

垃圾回收(Garbage Collection)
1. 找到内存中无用的垃圾资源
2. 清除这些垃圾并把内存让出来给其他对象使用。

python中的垃圾回收:
主要手段:引用计数
辅助手段:标记清除和分代回收机制

【引用计数】
每个对象都有PyObject,当对象有新的引用,ob_refcnt 增加;当引用被删除,ob_refcnt 就减少;当引用计数=0, 该对象生命就结束了

1. 导致引用计数+1的情况有哪些
    对象被创建,被一个变量引用,赋值操作:a = 8
    对象被另一个变量引用,赋值操作:b = a
    对象作为参数传递给函数:func(a)
    对象作为元素存储到容器中,比如:添加到列表、元组、字典、集合中:tmp = [a]

2. 导致引用计数-1的情况有哪些
    引用对象的变量被删除: del a
    引用这个对象的变量指向其他对象:a = "abc"
    函数作用域执行完毕,函数执行结束,函数中的局部变量就会消失
    对象所在的容器被销毁,或者从容器中删除了这个对象

【标记清除】
标记清除(Mark—Sweep)算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。
它分为两个阶段:第一阶段是标记阶段,GC会标记 所有的活动对象,第二阶段是回收 那些没有标记的非活动对象。

对象之间通过引用(指针)连在一起,构成一个有向图,对象是这个有向图的节点,而引用关系是这个有向图的边。
从根对象(root object)出发,沿着有向边遍历对象,可达的(reachable)对象标记为活动对象,不可达的对象就是要被清除的非活动对象。
根对象就是全局变量、调用栈、寄存器。
适用:容器对象,如:listdicttuple等,因为strint不可能造成循环引用
缺点:需要顺序扫描整个堆内存

【分代回收】
建立在标记清除技术上,以空间换时间
Python将内存,根据对象的存活时间划分为不同集合,每个集合称为一个代,即:年轻代(0)、中年代(1)、老年代(2)
对应三个链表,垃圾回收频率,随着对象的存活时间的增大而减小
新创建的对象被分配在年轻代,年轻代链表达到上线时,触发垃圾回收机制,回收那些可以被回收的对象,不会被回收的对象会被移动到中年代
以此类推,老年代中的对象,存活时间最久,甚至于存活于整个系统的生命周期内

【gc模块常用函数有哪些】
1、gc.set_debug(flags) 设置gc的debug日志,
    一般设置为gc.DEBUG_LEAK,可以看到内存泄露的对象
2、gc.collect([generation]) 显式执行垃圾回收,回收循环引用的对象。
    入参:
    0:只回收第0代对象,
    1:回收01代对象,
    2:回收012代对象,
    如果不传参数,默认值为2。
    返回:不可达(unreachable objects)对象的数量
3、gc.get_threshold() 获取gc模块自动执行垃圾回收的阈值/频率。
    返回:元组,分别为:第012代的阈值
    举例:gc.get_threshold()返回值为:(700, 10, 10),则:
         0代垃圾值到了700,就会执行gc.collect(0),回收0代的垃圾
         1代垃圾值到了710,就会执行gc.collect(1),回收01代的垃圾
         0代垃圾值到了700,就会执行gc.collect(2),回收012代的垃圾
4、gc.set_threshold(threshold[0], threshold[1], threshold[2]) 设置自动执行垃圾回收的阈值/频率。
5、gc.get_count() 获取当前自动执行垃圾回收的计数器,
    返回:元组,长度为3,分别为:第0代垃圾对象的数量、等0代链表遍历的次数,第1代链表遍历的次数

注意点:
gc模块不能处理的是,如果两个循环引用的对象都实现了__del__方法,那么将不会进行垃圾回收,因此尽量不要在类中实现自己的__del__方法。否则发生循环引用后就会产生内存泄露。

# 怎样查看一个对象的引用计数
# 用sys.getrefcount(a),举例如下:

import sys

a = 1
print(sys.getrefcount(a))  # 200
b = a
print(sys.getrefcount(a))  # 201
del b
print(sys.getrefcount(a))  # 200

# 注:调用sys.getrefcount()时,对象的引用会+1


refer:https://blog.csdn.net/zhoulei124/article/details/89021892
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值