- php的垃圾回收算法主要是參考這個論文
Concurrent Cycle Collection in Reference Counted Systems
前言
- 首先回顧一下引用計數(shù)法:引用計數(shù)(reference counting)
在引用計數(shù)算法中,對象的存活性可以通過引用關(guān)系的創(chuàng)建或刪除直接判定,而無需像追蹤式回收器那樣先通過堆遍歷找出所有的存活對象,然后再反向確定出未遍歷到的垃圾對象。
//todo - 對于基于最基本的引用計數(shù)法的垃圾回收算法優(yōu)點是非常快,但是缺點是循環(huán)引用的時候沒法回收會造成內(nèi)存泄露。而php垃圾回收算法是基于上述論文的引用計數(shù)+局部延時標(biāo)記的垃圾回收算法。
第一部分
先看偽代碼
// S 代表php中的對象
//purple 紫色表示對象在PossibleRoot 集合,但是在該集合中的不一定是紫色
// buffered(S) S是否在 PossibleRoot 集合
// black 黑色表示對象正在被使用或者已經(jīng)被回收了(不需要管了)
//gray 棕色表示對象可能被回收
//white 白色表示對象要被回收
//RC ReferenceCount 引用計數(shù)
//color(S) S 的顏色
//當(dāng)new 一個對象的時候,這時候不需要垃圾回收,這是最簡單的情況
Increase(S){
RC(S) = RC(S) + 1; //引用計數(shù) +1
color(S) = black; // 顏色染成黑色
}
//當(dāng)刪除一個指向S 的引用的時候
Decrease(S){
RC(S) = RC(S) - 1; //引用計數(shù)減1
if (RC(S) == 0) // 當(dāng)引用計數(shù)變?yōu)? 時候
Release(S); // 調(diào)用釋放函數(shù)Release()
else
PossibleRoot(S) ; //放入可能回收的PossibleRoot區(qū)域并染色成紫色purple
}
Release(S){
for T in children(S) // 遞歸調(diào)用減少子節(jié)點的引用
Decrement(T);
color(S)= black // 之后將該S節(jié)點染成黑色 (將被回收或者不需要回收 , 這里是前者)
if (! buffered(S)) // 判斷S 是否在PossibleRoot集合,在這個集合的在稍后的統(tǒng)一處理,
Free(S); //不在該集合且引用計數(shù)為0可以直接回收
}
PossibleRoot(S){
if (color(S)!= purple)
color(S)= purple
if (! buffered(S)){
buffered(S)= true
append S to Roots
}
}
第二部分
//主要是這個CollectCycles函數(shù)調(diào)用
//MarkRoot ScanRoots CollectRoots 來回收
CollectCycles(){
MarkRoot();
ScanToots();
ColletRoots();
}
//todo