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使用shelve模块实现简单数据存储的方法
May 20 Python
Python单例模式实例详解
Mar 01 Python
Python查找两个有序列表中位数的方法【基于归并算法】
Apr 20 Python
flask-socketio实现WebSocket的方法
Jul 31 Python
Python3 关于pycharm自动导入包快捷设置的方法
Jan 16 Python
Python安装Flask环境及简单应用示例
May 03 Python
Python实现性能自动化测试竟然如此简单
Jul 30 Python
Django自定义用户表+自定义admin后台中的字段实例
Nov 18 Python
使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解
Jan 25 Python
python 字符串的驻留机制及优缺点
Jun 19 Python
python爬虫请求头设置代码
Jul 28 Python
Python 的 __str__ 和 __repr__ 方法对比
Sep 02 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
全新的PDO数据库操作类php版(仅适用Mysql)
2012/07/22 PHP
支持中文、字母、数字的PHP验证码
2015/05/04 PHP
PHP的压缩函数实现:gzencode、gzdeflate和gzcompress的区别
2016/01/27 PHP
php魔术方法功能与用法实例分析
2016/10/19 PHP
jQuery Lightbox 图片展示插件使用说明
2010/04/25 Javascript
浅谈Javascript面向对象编程
2011/11/15 Javascript
jQuery操作表格(table)的常用方法、技巧汇总
2014/04/12 Javascript
js在数组中删除重复的元素自保留一个(两种实现思路)
2014/08/22 Javascript
jQuery实现列表的全选功能
2015/03/18 Javascript
angularjs学习笔记之完整的项目结构
2015/09/26 Javascript
javascript for-in有序遍历json数据并探讨各个浏览器差异
2015/11/30 Javascript
第二次聊一聊JS require.js模块化工具的基础知识
2016/04/17 Javascript
javascript数字验证的实例代码(推荐)
2016/08/20 Javascript
如何使用less实现随机下雪动画详解
2019/01/02 Javascript
微信小程序保存图片到相册权限设置
2020/04/09 Javascript
基于JavaScript实现表格隔行换色
2020/05/08 Javascript
JavaScript闭包原理与用法学习笔记
2020/05/29 Javascript
vue实现购物车加减
2020/05/30 Javascript
JS实现放大镜效果
2020/09/21 Javascript
[01:23:45]DOTA2-DPC中国联赛 正赛 CDEC vs Dragon BO3 第一场 1月22日
2021/03/11 DOTA
python self,cls,decorator的理解
2009/07/13 Python
部署Python的框架下的web app的详细教程
2015/04/30 Python
Python的Flask框架应用调用Redis队列数据的方法
2016/06/06 Python
Pytorch加载部分预训练模型的参数实例
2019/08/18 Python
pymysql 开启调试模式的实现
2019/09/24 Python
Python的几种主动结束程序方式
2019/11/22 Python
Python FFT合成波形的实例
2019/12/04 Python
Python系统公网私网流量监控实现流程
2020/11/23 Python
CSS3实现银灰色动画效果的导航菜单代码
2015/09/01 HTML / CSS
Html5跳转到APP指定页面的实现
2020/01/14 HTML / CSS
美国五金商店:Ace Hardware
2018/03/27 全球购物
英国领先的在线旅游和休闲零售商:lastminute.com
2019/01/23 全球购物
Linux管理员面试题 Linux admin interview questions
2016/07/08 面试题
求职自荐书范文
2013/12/04 职场文书
写作技巧:如何撰写一份优秀的营销策划书
2019/08/13 职场文书
MySQL范围查询优化的场景实例详解
2022/06/10 MySQL