发布网友 发布时间:2024-10-04 00:17
共1个回答
热心网友 时间:2024-10-07 05:32
分代回收是java垃圾回收的核心算法。该算法是基于这样的一个统计事实:对于程序,存在一定比例的内存块的生存周期比较短,而剩下的内存块,生存周期会比较长,甚至从程序开始持续到程序结束。生存期较短的对象大致能占到80%-90%。
因此,可以认为对象存在时间越长,越不可能是垃圾,应该越少取进行收集。
这样在执行标记-清除算法时可以有效减少遍历的对象数目,从而提高垃圾回收的效率,是一种以空间来换取时间的策略。
1.分代的内容python将所有对象分为0,1,2三代。
所有新建对象都是0代。
当某一代对象经历过垃圾回收,依然存活,就会被归入下一代对象。
每个代都由一个gc_generation结构体来进行维护。结构体中有三个变量。
head字段:可收集对象链表头部,代中的对象通过该链表维护。
threshold字段:仅当count超过本阈值时,python垃圾回收操作才会扫描本代对象。
count字段:计数器,不同代统计项目不一样。
每个gc_generation结构体链表头节点head字段都指向自己,也就是说每个可收集对象链表一开始都是空的。计数器字段count字段都被初始化为0,而threshold字段则有各自的策略。
2.分代回收策略初始化完成后,3个代对应的gc_generation数组大致如下:
python调用PyObject_GC_Alloc为需要跟踪的对象分配内存时,该函数将初生代count计数器加1,随后对象将接入初生代对象链表。当python调用PyObject_GC_Del释放垃圾对象内存时,该函数将初生代count计数器减1。PyObject_GC_Alloc自增count后如果超过阈值700,将调用collect_generations执行一次垃圾回收(GC)。
collect_generations函数从老生代开始,逐个遍历每个生代,找出需要执行回收操作的最老生代。随后调用collect_with_callback函数开始回收该生代,而该函数最终调用collect函数。
collect函数处理某个生代时,先将比他们年轻的生代计数器count重置为0,然后将他们的对象链表移除,与自己的拼接在一起后执行GCs算法,最后将下一个生代计数器加1。
总结起来有以下八点
(1)系统每新增 701 个需要 GC 的对象,Python 就执行一次 GC 操作
(2)一个对象创建后,随着时间推移将被逐步移入老生代,回收频率逐渐降低
(3)每执行 11 次新生代 GC ,触发一次中生代 GC
(4)每执行 11 次中生代 GC ,触发一次老生代 GC (老生代 GC 还受其他策略影响,频率更低)
(5)每次 GC 操作需要处理的生代可能是不同的,由 count 和 threshold 共同决定
(6)某个生代需要执行 GC ( count>hreshold ),在它前面的所有年轻生代也同时执行 GC
(7)对多个代执行 GC,Python 将它们的对象链表拼接在一起,一次性处理
(8)GC 执行完毕后,count 清零,而后一个生代 count 加 1