总结一句话:引用计时器为主,标记清除和分代回收为辅。
一:引用计时器:
1.环状双向链表-refchain:
python程序中所创建的对象全部存在这个refchain双向链表中,每个内存对象会产生一些数据,包括上一个对象,下一个对象,类型,引用计数器。如果是多个元素的对象,还会有元素的个数以及值。
2.这些对象中的数据如何提现出来的?
在c源码中封装了一个结构体---->pyobject,这个结构体中包含四个共享字段对应上面所说的四个数据,
还有一个结构体---->pyvarobject,这个结构体中包含元素的个数以及值。
3.引用计时器的原理:
创建/引用对象:
当创建不同的数据对象时,会在refchain这个双向链表中添加,然后其引用计数器的值会改变,默认为1;
当引用对象时,不会创建新的内存,直接在被引用对象的引用计时器加上1。
删除对象:
当删除对象时会让其引用计数器的值减一,
垃圾回收:
当引用计数器的值为0时,这个对象就是垃圾,则会回收(首先在refchain双向链表中移除,其次销毁内存,达到释放内存目的)。
二:标记清除:
目的:为了解决引用计数器循环引用的不足
原理:在refchain双向链表的基础上再加一个链表,专门放那些可能存在循环引用的对象(像list,dict,set等),在某种情况下,python内部会去扫描这个链表中的元素,检查是否 存在循环引用,如果存在,则双方的引用计数器减一,当引用计数器为0时,会清除。
三:分代回收:
目的: 为了解决标记清除存在的两个问题:什么时候扫描?当循环引用的链表很大时,扫描会很耗费时间。
原理:将链表再进行分级,一般分成三代,分别为0代,1代,2代,0代中最多可存700个元素,当0代元素中存满后,会进行扫描,如果存在循环引用,则会将双方的引用计时器值 减一,当引用计时器的值为0时,会进行清除,如此循环,当0代扫描满10次后会将未清除的上传到1代,如此循环,每代10次。
四:缓存机制(总结):
在python程序中维护了一个双向循环链表refchain,这个链表存着所有的对象,每种类型都有一个引用计数器,默认为一,当进行引用操作,会加一,删除操作会减一,当引用计数器值为0时,会进行垃圾回收,即链表中移除,内存回收。但是python中有多个元素组成的对象可能会存在循环引用的问题,为了解决这个问题,引入了标记清除和分代回收,这两个会将链表再refchain基础上再增加三个链表,分别叫0代,1代,2代,当每个链表到达阙值时,会触发扫描,进而标记清除(存在循环引用则引用计数器减一,当引用计数器为0时,链表清除,释放内存)。