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中assert用法实例分析
Apr 30 Python
python制作一个桌面便签软件
Aug 09 Python
利用Python命令行传递实例化对象的方法
Nov 02 Python
python中pandas.DataFrame对行与列求和及添加新行与列示例
Mar 12 Python
Python对List中的元素排序的方法
Apr 01 Python
python将回车作为输入内容的实例
Jun 23 Python
详解Python下Flask-ApScheduler快速指南
Nov 04 Python
django框架实现模板中获取request 的各种信息示例
Jul 01 Python
python 单线程和异步协程工作方式解析
Sep 28 Python
Python3 sys.argv[ ]用法详解
Oct 24 Python
Python计算不规则图形面积算法实现解析
Nov 22 Python
pandas中的ExcelWriter和ExcelFile的实现方法
Apr 24 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
如何选购合适的收音机
2021/03/01 无线电
php生成局部唯一识别码LUID的代码
2012/10/06 PHP
destoon实现调用当前栏目分类及子分类和三级分类的方法
2014/08/21 PHP
JavaScript 封装Ajax传递的数据代码
2009/06/05 Javascript
js 字符串操作函数
2009/07/25 Javascript
用jquery实现自定义风格的滑动条实现代码
2011/04/26 Javascript
浅谈 javascript 事件处理
2015/01/04 Javascript
ionic cordova一次上传多张图片(类似input file提交表单)的实现方法
2016/12/16 Javascript
js中document.referrer实现移动端返回上一页
2017/02/22 Javascript
Windows下Node.js安装及环境配置方法
2017/09/18 Javascript
mui框架 页面无法滚动的解决方法(推荐)
2018/01/25 Javascript
JS实现方形抽奖效果
2018/08/27 Javascript
详解mpvue scroll-view自动回弹bug解决方案
2018/10/01 Javascript
vue cli使用融云实现聊天功能的实例代码
2019/04/19 Javascript
详解Vue 项目中的几个实用组件(ts)
2019/10/29 Javascript
原生js滑动轮播封装
2020/07/31 Javascript
如何在JavaScript中使用localStorage详情
2021/02/04 Javascript
在Python中操作列表之list.extend()方法的使用
2015/05/20 Python
PyQt5 多窗口连接实例
2019/06/19 Python
获取django框架orm query执行的sql语句实现方法分析
2019/06/20 Python
python多线程扫描端口(线程池)
2019/09/04 Python
Python调用OpenCV实现图像平滑代码实例
2020/06/19 Python
详解python程序中的多任务
2020/09/16 Python
用CSS3实现无限循环的无缝滚动的实例代码
2017/07/04 HTML / CSS
丝芙兰法国官网:SEPHORA法国
2016/09/01 全球购物
来自全球大都市的高级街头服饰:Pegador
2018/01/03 全球购物
CHRONEXT英国:您的首选奢华腕表目的地
2020/03/30 全球购物
Internet体系结构
2014/12/21 面试题
管理学专业个人求职信范文
2013/09/21 职场文书
出国考察邀请函
2014/01/21 职场文书
优秀小学生家长评语
2014/01/30 职场文书
2014年工程部工作总结
2014/11/25 职场文书
电力企业职工培训心得体会
2016/01/11 职场文书
求职信:求职应该注意的问题
2019/04/24 职场文书
年会邀请函的格式及范文五篇
2019/11/02 职场文书
MySQL时间设置注意事项的深入总结
2021/05/06 MySQL