python垃圾回收机制有哪些_主流的垃圾回收机制都有哪些?

看大家科普差不多了,我来个角度刁钻的

python的垃圾收集,你能找到的资料几乎都说是引用计数+标记清除

但是这个“标记清除”跟一般的标记清除还是有点差别的,全名是“局部标记清除”,它基于引用计数

这个算法最早好像是出现在fortran,虽然流程都是“确定根集合->标记->清除”,但是和普通MS算法不同的是,第一步确定根集合是基于引用计数来做的,它不是以“栈、全局变量”之类的东西作为根集合起点,而是随便给个堆上对象的集合都可以根据引用计数算出这个集合的“根”,也就是说根本不需要跟踪或扫描栈和全局区域

具体做法也很简单:对于任何对象集合,我们先弄个表存它们的引用计数的副本,然后把内部引用都拆掉,所谓内部引用是指这个集合中的某个对象引用了另一个本集合内部的对象,拆的过程中减少引用计数,当然是在副本表里面减少

全部拆除后,引用计数依然不为0的,就是根集合,然后开始标记过程,标记其实不需要任何染色,只要逐步恢复引用并增加副本表的引用计数即可

最后,副本表中引用计数为0的,就是垃圾

例如:

随便抽出6个对象作为一个集合,这个集合有外部进来的连接(到a和b),也有到外部的连接(c引用了外面某个对象),但这个都无所谓,重要的是其内部连接,右边是引用计数表,然后我们拆掉所有内部连接:

根集合就是a和b了,然后我们开始标记并恢复引用计数:

从a和b出发可达的都被回复了,引用计数还是0的就是这个集合内部循环引用的垃圾(e和f)

如果你把所有对象看做一个集合,那么这个算法每次都可以回收所有垃圾,当然,性能是另码事

你也可以将对象划分为一个个小的集合,分别来回收,但这时候的效果就取决于你是否能尽量将循环引用的垃圾划分到每个集合中,集合划分粒度越粗,回收效果越好,但是速度越慢,反之亦然

python的做法是分代,每一代作为一个集合,其他语言的GC中的分代需要额外记录各代之间的引用,但是python基于引用计数,反而不需要了

当然,再说一句,性能是另码事……

=================

补充:这个算法作为引用计数的补充,最大好处就是不需要runtime环境支持栈和全局空间的扫描,譬如说,你在C++中用智能指针配合自己写的对象申请和释放器,理论上讲是可以解决循环引用问题而不需要关心栈和全局区的“根集合”,这样就算智能指针和普通手工申请释放两种机制混合用也没问题,唯一麻烦的地方是,你需要对每个shared_ptr维护的对象实现遍历引用和标记。另一个好处是,虽然你的代码有很多类都会用引用计数来维护,但并不是每个类都是容器类,而非容器类的对象显然不可能出现循环引用,单纯的引用计数就足够了,因此上面算法仅针对容器即可

更进一步地,如果上面这些用一个编译器分析处理,还可以分析出那些类是会进入引用计数管理,给这些类自动生成标记清除的相关方法代码,以及进一步分析哪些类可能形成循环引用,哪些不可能形成,最终这个算法只需要处理必要的类型的对象即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值