Lua GC 之 Generational
lua在5.2版本为我们带来了分代GC(分代GC的优点,自己查编译原理去),默认不开启的,默认使用的还是增量GC。
简单描述下lua的分代GC:分代(非增量),而且也只分两代,并不是我们大家常听说的三代。为什么只分两代呢,原因很简单,它只是巧妙的利用了目前已经实现的增量GC机制。
它与 增量GC 的最大差别在于,增量GC 的 sweep 阶段会处理整个链表的对象,并标记为 currrent white (或者称为 翻转白色),而 分代GC 仅仅只处理链表前端的新对象,并标记为old。
基础:lua的对象链表为单向链表,新对象插入链表最前面;对象从创建时就插入 allgc,GC运行时,对象也会被放入 gray、grayagain。(为了简化,这里不考虑弱表 weak table、可析构对象 finalizer 的处理)
1 新GC周期开始,lua对象链上所有对象都是标记为 old 的对象;
虚拟机运行阶段:
2 有新对象创建,插入对象链的最前端。
3 如果新对象被 old 对象所引用,Write Barrier 自动将此新对象插入 gray 链——unscan list(如果old对象是容器——table,则将 old 对象放入grayagain 链——rescan list)
2、3步骤反复执行直至满足触发条件,虚拟机停止,GC开始工作
GC运行阶段:
4 遍历 gray 链,作标记工作(propagate)
5 遍历 grayagain 链,作标记工作(propagate)
至此GC的 propagate 阶段完成
6 清扫新对象链中新对象(从 allgc 链开始,至第一个标记为 old 对象止):释放的不可达对象内存;可达对象标记为 old
GC工作结束。流程又从1开始
下表为 global_State 中 GC 相关的变量
/* ** `global state', shared by all threads of this state */ typedef struct global_State { //新分配对象颜色 lu_byte currentwhite; //GC对象链 GCObject *allgc; /* list of all collectable objects */ // 待扫描对象链 unscan list GCObject *gray; /* list of gray objects */ // 需再次扫描对象链 rescan list GCObject *grayagain; /* list of objects to be traversed atomically */ //控制参数 int gcpause; /* size of pause between successive GCs */ int gcmajorinc; /* how much to wait for a major GC (only in gen. mode) */ int gcstepmul; /* GC `granularity' */ } global_State;
分代GC 可以参考lua邮件讨论 Generational GC (was Re: A review of changes between 5.1 and 5.2-work3)
如果对 lua 5.1 的GC的实现细节感兴趣,可以参考云风针对 lua 5.1.4 的 Lua GC 的源码剖析
posted on 2012-12-26 16:52 JesseFang 阅读(1253) 评论(0) 编辑 收藏 举报