python 垃圾收集机制的实例详解


Posted in Python onAugust 20, 2017

 python 垃圾收集机制的实例详解

pythonn垃圾收集方面的内容如果要细讲还是挺多的,这里只是做一个大概的概括

Python最主要和绝大多数时候用的都是引用计数,每一个PyObject定义如下:

#define PyObject_HEAD          \ 
  Py_ssize_t ob_refcnt;        \ 
  struct _typeobject *ob_type; 
typedef struct _object { 
  PyObject_HEAD 
} PyObject;

每个pyobject都有一个refcnt来记录他们自己的引用数,一旦引用数为0,就进行回收

引用计数的优点在于实时性,一旦没有其他对象引用了,就能立马进行回收,看起来十分不错,但为什么好多语言都没有采用该方案,因为引用计数有一个致命的缺点,无法解决循环引用问题,比如:

a = [] 
b = [] 
a.append(b) 
b.append(a)

其实并没有其他变量引用a,b那么他们实际上应该被回收掉,但由于相互引用的关系,他们的引用数都为1,无法被回收。

在python中,相互引用的问题仅仅存在与容器里面,例如list,dictionary,class,instance。为了解决该问题,python引入了标记——清除和分代——回收另外两种机制。

事实上,python中的容器并没有之前讲的那么简单,在pyobject_head之前,还有一个PyGC_head,也就是专门用来处理容器的循环引用问题的。

typedef union _gc_head { 
  struct { 
    union _gc_head *gc_next; 
    union _gc_head *gc_prev; 
    Py_ssize_t gc_refs; 
  } gc; 
  long double dummy; /* force worst-case alignment */ 
} PyGC_Head;

所有创建的容器类的对象都会被记录到可收集对象链表中,通过上面的结构我们可以知道其实是构建了一个双向链表,这样我们就可以来跟踪所有可能产生循环引用的情况了。而像int,string等简单的不是容器类型的,只要引用技术为0,就会被回收。但是如果频繁的malloc和free会严重影响效率,所以python采用了大量的对象池来提高效率。

标记——清除包括了垃圾回收的两个方面:(1)寻找可以回收的对象(2)回收对象,python中的标记会从root object开始,遍历所有容器类对象,查找出可以通过引用来到达的一些对象,把他们放到由reachable维护的链表中,对于不能到达的放到unbreachable维护的链表中,此过程结束之后,对unreachable里面的元素进行回收即可。

那么如何对应之前循环引用的情况呢?python里面会产生一个有效的引用数,存在gc.gc_refs里面,像上面的a,b真实引用数为1,但有效的引用数为0(循环中的引用数都减1),由于不能直接改pyobjec里面的refcnt,否则会产生一系列问题,我们可以将有效的引用数记到gc.gc_refs里面,那么a,b 的真实有效引用数都为0,所以他们可以被回收。

下面是另外一种情况:

a = [] 
b = [] 
c = a 
a.append(b) 
b.append(a)

这里ab也是循环引用,但是多了c来引用a,通过计算循环中的有效引用计数可得a的引用数为1,b的引用数为0,看起来b应该被回收,但实际上因为a是不可被回收的,a又引用了b,所以b也会被放入在reachable链表中,不被回收,其gc.gc_refs还是会被置1的。

另外一种分代回收,是说内存中有的对象会频繁的malloc和free,有的则比较长久,如果一个对象经过多次垃圾收集和清除之后还存在的话,那么我们就可以认为,这个对象是长时间有用的,不用去频繁检测回收它。python中分为3代,分别是3个链表维护,0代最多维护700个对象,1代10个,2代10个,如果对象超过这个数了,就会调用标记——清除算法来进行回收。可以想到,0代的对象经过一段时间后会到1代2代中去,然后对它们的检测回收会相比于0代的不那么频繁了

要注意的是,python主要的机制还是引用技术,标记——清除和分代收集只是为了弥补引用计数的缺点而添加的,也就是说,后两者基本只在容器类的循环引用上能发挥作用

以上就是python 垃圾收集机制的实例详解,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Python 相关文章推荐
python 链接和操作 memcache方法
Mar 04 Python
python实现上传下载文件功能
Nov 19 Python
Python中一些不为人知的基础技巧总结
May 19 Python
pyhanlp安装介绍和简单应用
Feb 22 Python
python Tcp协议发送和接收信息的例子
Jul 22 Python
如何基于python实现画不同品种的樱花树
Jan 03 Python
Keras 快速解决OOM超内存的问题
Jun 11 Python
Python 的 __str__ 和 __repr__ 方法对比
Sep 02 Python
Python JSON常用编解码方法代码实例
Sep 05 Python
详解KMP算法以及python如何实现
Sep 18 Python
Django migrate报错的解决方案
May 20 Python
Python tensorflow卷积神经Inception V3网络结构
May 06 Python
python 实现tar文件压缩解压的实例详解
Aug 20 #Python
详解Python 序列化Serialize 和 反序列化Deserialize
Aug 20 #Python
Python中input与raw_input 之间的比较
Aug 20 #Python
Python 基础教程之str和repr的详解
Aug 20 #Python
Python实现爬取需要登录的网站完整示例
Aug 19 #Python
Python获取当前页面内所有链接的四种方法对比分析
Aug 19 #Python
Python基于numpy灵活定义神经网络结构的方法
Aug 19 #Python
You might like
PHP网页游戏学习之Xnova(ogame)源码解读(三)
2014/06/23 PHP
php获取textarea的值并处理回车换行的方法
2014/10/20 PHP
CI(CodeIgniter)框架实现图片上传的方法
2017/03/24 PHP
JavaScript插件化开发教程 (三)
2015/01/27 Javascript
整理Javascript流程控制语句学习笔记
2015/11/29 Javascript
Javascript实现图片加载从模糊到清晰显示的方法
2016/06/21 Javascript
jQuery实现边框动态效果的实例代码
2016/09/23 Javascript
微信小程序 摇一摇抽奖简单实例实现代码
2017/01/09 Javascript
jQuery插件FusionCharts实现的Marimekko图效果示例【附demo源码】
2017/03/24 jQuery
vue使用xe-utils函数库的具体方法
2018/03/06 Javascript
Js面试算法详解
2018/04/08 Javascript
JavaScript学习笔记之DOM基础操作实例小结
2019/01/09 Javascript
使用JQuery自动完成插件Auto Complete详解
2019/06/18 jQuery
[00:35]DOTA2上海特级锦标赛 EG战队宣传片
2016/03/04 DOTA
详解Python中的文本处理
2015/04/11 Python
python检查URL是否正常访问的小技巧
2017/02/25 Python
Python字典实现简单的三级菜单(实例讲解)
2017/07/31 Python
Python使用Selenium+BeautifulSoup爬取淘宝搜索页
2018/02/24 Python
Python tkinter的grid布局及Text动态显示方法
2018/10/11 Python
Django框架实现的简单分页功能示例
2018/12/04 Python
关于tf.TFRecordReader()函数的用法解析
2020/02/17 Python
python GUI库图形界面开发之PyQt5信号与槽机制、自定义信号基础介绍
2020/02/25 Python
7款设计巧妙的css3飘带状3D立体效果的导航菜单和表单窗口
2013/02/04 HTML / CSS
利用HTML5绘制点线面组成的3D图形的示例
2015/05/12 HTML / CSS
HTML5 Canvas实现图片缩放、翻转、颜色渐变的代码示例
2016/02/28 HTML / CSS
马来西亚网上购物平台:ezbuy
2018/02/13 全球购物
法国最大的在线眼镜店:EasyLunettes
2019/08/26 全球购物
德国专业木制品经销商:Holz-Direkt24
2019/12/26 全球购物
怎样在 Applet 中建立自己的菜单(MenuBar/Menu)?
2012/06/20 面试题
电子商务专业个人的自我评价
2013/12/19 职场文书
毕业生个人求职自荐信
2014/02/26 职场文书
2015个人年度工作总结范文
2015/05/28 职场文书
超级礼物观后感
2015/06/15 职场文书
创业计划书之韩国烧烤店
2019/09/19 职场文书
InterProcessMutex实现zookeeper分布式锁原理
2022/03/21 Java/Android
提高系统的吞吐量解决数据库重复写入问题
2022/04/23 MySQL