- php的垃圾回收算法主要是参考这个论文
Concurrent Cycle Collection in Reference Counted Systems
前言
- 首先回顾一下引用计数法:引用计数(reference counting)
在引用计数算法中,对象的存活性可以通过引用关系的创建或删除直接判定,而无需像追踪式回收器那样先通过堆遍历找出所有的存活对象,然后再反向确定出未遍历到的垃圾对象。
//todo - 对于基于最基本的引用计数法的垃圾回收算法优点是非常快,但是缺点是循环引用的时候没法回收会造成内存泄露。而php垃圾回收算法是基于上述论文的引用计数+局部延时标记的垃圾回收算法。
第一部分
先看伪代码
// S 代表php中的对象
//purple 紫色表示对象在PossibleRoot 集合,但是在该集合中的不一定是紫色
// buffered(S) S是否在 PossibleRoot 集合
// black 黑色表示对象正在被使用或者已经被回收了(不需要管了)
//gray 棕色表示对象可能被回收
//white 白色表示对象要被回收
//RC ReferenceCount 引用计数
//color(S) S 的颜色
//当new 一个对象的时候,这时候不需要垃圾回收,这是最简单的情况
Increase(S){
RC(S) = RC(S) + 1; //引用计数 +1
color(S) = black; // 颜色染成黑色
}
//当删除一个指向S 的引用的时候
Decrease(S){
RC(S) = RC(S) - 1; //引用计数减1
if (RC(S) == 0) // 当引用计数变为0 时候
Release(S); // 调用释放函数Release()
else
PossibleRoot(S) ; //放入可能回收的PossibleRoot区域并染色成紫色purple
}
Release(S){
for T in children(S) // 递归调用减少子节点的引用
Decrement(T);
color(S)= black // 之后将该S节点染成黑色 (将被回收或者不需要回收 , 这里是前者)
if (! buffered(S)) // 判断S 是否在PossibleRoot集合,在这个集合的在稍后的统一处理,
Free(S); //不在该集合且引用计数为0可以直接回收
}
PossibleRoot(S){
if (color(S)!= purple)
color(S)= purple
if (! buffered(S)){
buffered(S)= true
append S to Roots
}
}
第二部分
//主要是这个CollectCycles函数调用
//MarkRoot ScanRoots CollectRoots 来回收
CollectCycles(){
MarkRoot();
ScanToots();
ColletRoots();
}
//todo