GC标记-清除算法(Mark Sweep GC)
GC标记-清除算法自问世以来,一直到半个世纪后的今天,依然是处理各类程序的所用的经典算法。典型的标记-清除算法很简单,
现在更常用的是与其他的算法巧妙结合达成意想不到的效果。
GC标记-清除算法顾名思义,就是标记和清除。标记活动的对象,清除没有标记或者是说没有在活动的对象。
标记:
在标记阶段中,垃圾收集器会给所有活动打上标记即mark=true。标记函数根据传入的参数为根,由根(链表头)再逐步搜索(一般采用深度优先搜索,因为DFS比BFS更能压低内存使用量),直到没有下一个对象为止。做为一名工程师看看伪代码或许更能理解这个过程。
mark_phase() {
for(r:$roots) //遍历所有根
marks(*r)
}
mark(obj) {
if(obj.mark == false) //设置标记位
obj.mark = true
for(child: children(obj)) 遍历以该根为起点的对象
mark(*child)
}
清除 :
和标记阶段相同,清除阶段也同样需要遍历堆空间中所有的对象。若对象标记位为false则进行垃圾回收处理,在最典型的标记-清除算法中是对每一个对象的空间利用头插法建立空闲链表。
sweep_phase() {
sweeping = $heap_start; //堆内存中首地址
while(sweeping<$heap_end) {
if(sweep.mark == true)
sweep.mark = false;
else {
//头插法
sweeping. next = $free_list;
$free_list = sweeping;
sweep += sweeping. size;
}
}
}
建立空闲链表后,若系统需要分配空间则直接从空闲链表中索取。具体做法和我们操作系统中内存分配空间类似,常见的有First-fit, Best_fit, Worst_fit。我们这里考虑到查找空闲链表所需要的时间采用First-fit更为合适。
Q.E.D.