python 垃圾回收机制
-
引用计数
-
标记清楚
-
分代回收
这个大家肯定都知道!今天呢就深入的了解一下吧
引用计数
从底层c语言源码中看出 python在创建一个对象的时候,会把它放在一个环状双向链表中(refchain)
根据对象类型的不同,找到对应的结构体创建相关数据放到双向链表中
-
pyobject 存[上一个对象,下一个对象,类型,引用次数] 用于对象:str,int,float
-
pyvarobject 存[上一个对象,下一个对象,类型,引用次数,ob_size] 用于多元素对象
每删除一个对象时引用次数(ob_refcot)加一,当ob_refcot为0时做两步:1.移除refchain的对象 2.将对象销毁归还内存
存在的问题
当对象出现循环引用的时候解决不了了
标记清除
目的
用来解决对象循环引用的问题
实现
在python底层再维护一个链表,专门存放那些可能会循环引用的对象,在python内部某个情况下触发,回去扫描可能存在循环引用链表中的每个元素,检查是否有循环引用,如果有就放双发的引用计数都减1,引用计数变为0就垃圾回收,不为0就说明还有对象用到它们。
存在的问题
1.什么时候扫描?
2.可能存在循环引用的链表扫描代价大,耗时!
分代回收
目的
解决标记清除存在的问题,将可能存在引用的对象维护成3个链表
- 0代:对象个数达到700个扫描一次
- 1代:0代扫描10次,1代扫描一次
- 2代:1代扫描10次,2代扫描一次
优化
python对垃圾回收机制的优化 python缓存
小数据池 int
为了避免重复创建和销毁一些常见对象。在启动解释器时,python内存会创建 -5,-4 … 256 小数据池
str 池
free_list (float 80/list 80/tuple 20/dict 80)
当一个对象的引用计数为0时,内部不会直接回收,而是将对象添加到free_list 链表中当缓存,以后再去创建对象时,不在重新开辟内存,而是直接使用free_list 。 当free_list 链表存满后再销毁 最大80个,但是tuple最大20个 [0,1,2,…] 0为空,1存放一个元素的元组 最大2000个,2存放两个元素的元组 最大2000个,直到20。