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 的源码剖析

原文地址:https://www.cnblogs.com/JesseFang/p/2834378.html