python垃圾回收机制

参考自:

https://baijiahao.baidu.com/s?id=1575523435249123&wfr=spider&for=pc

https://www.jianshu.com/p/1e375fb40506

Python的GC模块主要运用了引用计数来跟踪和回收垃圾,在引用计数的基础上,还可以通过“标记-清除”解决容器对象可能产生的循环引用的问题。通过分代回收以空间换取时间进一步提高垃圾回收的效率,也就是说python采用的是引用计数机制为主,标记清除和分代收集为辅的策略。

引用计数机制:(自动垃圾回收方式)

原理:

python里每一个东西都是对象,它们的核心就是一个结构体:PyObject

typedef struct_object {
 int ob_refcnt;
 struct_typeobject *ob_type;
} PyObject;

PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少

#define Py_INCREF(op)   ((op)->ob_refcnt++) //增加计数
#define Py_DECREF(op) \ //减少计数
    if (--(op)->ob_refcnt != 0) \
        ; \
    else \
        __Py_Dealloc((PyObject *)(op))

当引用计数为0时,该对象生命就结束了。

原理大致概述:

引用计数是一种最直观,最简单的垃圾收集技术,当一个对象的引用被创建或者复制时,对象的引用计数加1;当一个对象的引用被销毁时,对象的引用计数减1,当对象的引用计数减少为0时,就意味着对象已经再没有被使用了,python解释器就认为这个数据是垃圾,进行垃圾回收,释放空间。

优点:

引用计数有一个很大的优点,即实时性,任何内存,一旦没有指向它的引用,就会被立即回收,而其他的垃圾收集技术必须在某种特殊条件下才能进行无效内存的回收

缺点:

如果出现循环引用的话,每个对象的引用都不会为0,引用计数机制就不再起有效的作用了,这个时候就该标记-清除上场了!


标记-清除:

标记-清除的出现打破了循环引用,也就是它只关注那些可能会产生循环引用的对象,显然,像是PyIntObject、PyStringObject这些不可变对象是不可能产生循环引用的,因为它们内部不可能持有其它对象的引用。Python中的循环引用总是发生在container对象之间,也就是能够在内部持有其它对象的对象,比如list、dict、class等等。这也使得该方法带来的开销只依赖于container对象的的数量。

原理:

将集合中对象的引用计数复制一份副本,这个计数副本的作用是寻找root object集合(该集合中的对象是不能被回收的)。当成功寻找到root object集合之后,首先将现在的内存链表一分为二,一条链表中维护root object集合,成为root链表,而另外一条链表中维护剩下的对象,成为unreachable链表。一旦在标记的过程中,发现现在的unreachable可能存在被root链表中直接或间接引用的对象,就将其从unreachable链表中移到root链表中;当完成标记后,unreachable链表中剩下的所有对象就是名副其实的垃圾对象了,接下来的垃圾回收只需限制在unreachable链表中即可。

如果两个对象的引用计数都为 1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被
回收的,也就是说,它们的引用计数虽然表现为非 0,但实际上有效的引用计数为 0。所以先将循环引
用摘掉,(比如从对象A出发,沿着引用寻找到对象B,把对象B的引用计数减去1;然后沿着B对A的引用回到A,把A的引用计数减1,这样就可以把这层循环引用关系给去掉了。)就会得出这两个对象的有效计数。

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

缺点:该机制所带来的额外操作和需要回收的内存块成正比。


分代回收

原理:

分代回收策略着眼于提升垃圾回收的效率。研究表明,任何语言,任何环境的编程中,对于变量在内存中的创建/销毁,总有频繁和不那么频繁的。比如任何程序中总有生命周期是全局的、局部的变量。

而在垃圾回收的过程中,其实在进行垃圾回收之前还要进行一步垃圾检测,即检查某个对象是不是垃圾,该不该被回收。当对象很多,垃圾检测将耗费大量的时间而真的垃圾回收花不了多久。对于这种多对象程序,我们可以把一些进行垃圾回收频率相近的对象称为“同一代”的对象。垃圾检测的时候可以对频率较高的“代”多检测几次,反之,进行垃圾回收频率较低的“代”可以少检测几次。这样就可以提高垃圾回收的效率了。


调优手段
1.手动垃圾回收
2.调高垃圾回收阈值
3.避免循环引用(手动解循环引用和使用弱引用)
 


完结!(*^▽^*)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值