Python回收机制

标签: 回收机制 Python 内存
32人阅读 评论(0) 收藏 举报
分类:

Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题。通过“分代回收”(generation collection)以空间换取时间来进一步提高垃圾回收的效率。

一、引用计数

在Python中,大多数对象的生命周期都是通过对象的引用计数来管理的。从广义上来讲,引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。

原理:当一个对象的引用被创建或者复制时,对象的引用计数加1;当一个对象的引用被销毁时,对象的引用计数减1;当对象的引用计数减少为0时,就意味着对象已经没有被任何人使用了,可以将其所占用的内存释放了。

虽然引用计数必须在每次分配和释放内存的时候加入管理引用计数的动作,然而与其他主流的垃圾收集技术相比,引用计数有一个最大的有点,即“实时性”,任何内存,一旦没有指向它的引用,就会立即被回收。而其他的垃圾收集计数必须在某种特殊条件下(比如内存分配失败)才能进行无效内存的回收。

引用计数机制执行效率问题:引用计数机制所带来的维护引用计数的额外操作与Python运行中所进行的内存分配和释放,引用赋值的次数是成正比的。而这点相比其他主流的垃圾回收机制,比如“标记-清除”,“停止-复制”,是一个弱点,因为这些技术所带来的额外操作基本上只是与待回收的内存数量有关。

如果说执行效率还仅仅是引用计数机制的一个软肋的话,那么很不幸,引用计数机制还存在着一个致命的弱点,正是由于这个弱点,使得侠义的垃圾收集从来没有将引用计数包含在内,能引发出这个致命的弱点就是循环引用(也称交叉引用)。

问题说明:

循环引用可以使一组对象的引用计数不为0,然而这些对象实际上并没有被任何外部对象所引用,它们之间只是相互引用。这意味着不会再有人使用这组对象,应该回收这组对象所占用的内存空间,然后由于相互引用的存在,每一个对象的引用计数都不为0,因此这些对象所占用的内存永远不会被释放。比如:

Python

1
2
3
4
5
6
7
8
a = []
b = []
a.append(b)
b.append(b)
print a
[[[…]]]
print b
[[[…]]]
这一点是致命的,这与手动进行内存管理所产生的内存泄露毫无区别。

要解决这个问题,Python引入了其他的垃圾收集机制来弥补引用计数的缺陷:“标记-清除”,“分代回收”两种收集技术。

二、标记-清除

“标记-清除”是为了解决循环引用的问题。可以包含其他对象引用的容器对象(比如:list,set,dict,class,instance)都可能产生循环引用。

我们必须承认一个事实,如果两个对象的引用计数都为1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的,也就是说,它们的引用计数虽然表现为非0,但实际上有效的引用计数为0。我们必须先将循环引用摘掉,那么这两个对象的有效计数就现身了。假设两个对象为A、B,我们从A出发,因为它有一个对B的引用,则将B的引用计数减1;然后顺着引用达到B,因为B有一个对A的引用,同样将A的引用减1,这样,就完成了循环引用对象间环摘除。

但是这样就有一个问题,假设对象A有一个对象引用C,而C没有引用A,如果将C计数引用减1,而最后A并没有被回收,显然,我们错误的将C的引用计数减1,这将导致在未来的某个时刻出现一个对C的悬空引用。这就要求我们必须在A没有被删除的情况下复原C的引用计数,如果采用这样的方案,那么维护引用计数的复杂度将成倍增加。

原理:“标记-清除”采用了更好的做法,我们并不改动真实的引用计数,而是将集合中对象的引用计数复制一份副本,改动该对象引用的副本。对于副本做任何的改动,都不会影响到对象生命走起的维护。

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

三、分代回收

背景:分代的垃圾收集技术是在上个世纪80年代初发展起来的一种垃圾收集机制,一系列的研究表明:无论使用何种语言开发,无论开发的是何种类型,何种规模的程序,都存在这样一点相同之处。即:一定比例的内存块的生存周期都比较短,通常是几百万条机器指令的时间,而剩下的内存块,起生存周期比较长,甚至会从程序开始一直持续到程序结束。

从前面“标记-清除”这样的垃圾收集机制来看,这种垃圾收集机制所带来的额外操作实际上与系统中总的内存块的数量是相关的,当需要回收的内存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收带来的额外操作就越少;反之,当需回收的内存块越少时,垃圾检测就将比垃圾回收带来更少的额外操作。为了提高垃圾收集的效率,采用“空间换时间的策略”。

原理:将系统中的所有内存块根据其存活时间划分为不同的集合,每一个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减小。也就是说,活得越长的对象,就越不可能是垃圾,就应该减少对它的垃圾收集频率。那么如何来衡量这个存活时间:通常是利用几次垃圾收集动作来衡量,如果一个对象经过的垃圾收集次数越多,可以得出:该对象存活时间就越长。

查看评论

Python的垃圾回收机制(三)之回收机制

0. 背景之前介绍了Python垃圾回收的简介和内存模型,这里会对前几篇提到的回收机制进行代码剖析。注意这里用到的术语,如有疑问移步(一)简介查看。1. 标记清除中的GCPython使用引用计数来管理...
  • tab_space
  • tab_space
  • 2016-09-07 14:59:15
  • 565

面向对象——概念(成员变量、静态变量、成员方法、静态方法、垃圾回收机制、重载、包)

转自 : http://www.toutiao.com/a6396256447914918145/?tt_from=mobile_qq&utm_campaign=client_share&app=ne...
  • xiaoxianerqq
  • xiaoxianerqq
  • 2017-03-15 15:47:55
  • 301

[Python]垃圾回收机制

Python 垃圾回收机制引用计数Python中一切皆对象。PyObject中有个obj_refcnt字段,用于记录对象被引用的次数。标记清除为解决对象之间循环引用问题,借鉴Ruby的标记清除机制,P...
  • cn_wk
  • cn_wk
  • 2016-06-18 21:04:08
  • 829

python 回收机制

1.引用计数为主,标记清除和分代回收为辅助。 2.引用计数:当对象的引用计数为0,python的解释器则会释放该对象的内存。 3.标记清除:“标记-清除”是为了解决循环引用的问题。可以包含其他对象...
  • shaququ
  • shaququ
  • 2017-08-15 15:32:24
  • 101

20171021_python内存回收机制

作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!看到一篇不错的文章,转了。语言的内存管理是语言设计的一个重要方面。它是决定语言性能的...
  • c412745699
  • c412745699
  • 2017-10-21 10:14:25
  • 63

python垃圾回收机制!

现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++里用户自己管理维护内存的方式。自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐...
  • qq_39248703
  • qq_39248703
  • 2017-07-30 20:11:16
  • 493

python高级部分课件

  • 2017年10月11日 12:57
  • 21.82MB
  • 下载

Java基础之详细理解回收机制

在以前从事C/C++开发的时候,内存的管理一直是需要被谨慎考虑的内容。在C语言中,我们使用库函数malloc()和free()两个库函数来实现从堆中分配内存与释放,而C++则使用操作符new和dele...
  • sjm19901003
  • sjm19901003
  • 2015-07-31 21:12:59
  • 1428

第四章 储存管理.pdf

  • 2009年08月03日 21:25
  • 332KB
  • 下载

深入理解Java回收机制

来源:http://www.importnew.com/16173.html 一、垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问...
  • liuyi1207164339
  • liuyi1207164339
  • 2016-03-18 19:57:24
  • 1206
    个人资料
    持之以恒
    等级:
    访问量: 1276
    积分: 234
    排名: 34万+
    文章分类