Lua GC

作者: 此年此景 | 来源:发表于2018-10-28 16:56 被阅读0次

    一、GC的原理及其算法设计

    不同的语言,对GC算法的设计不同,常见的GC算法是引用计数和Mark-Sweep算法, c#采用的是Mark-sweep && compact算法, Lua采用的是Mark-sweep算法,分开说一下:

    引用计数算法:在一个对象被引用的情况下,将其引用计数加1,反之则减1,如果计数值为0,则在GC的时候回收,这个算法有个问题就是循环引用。

    Mark-sweep算法:每次GC的时候,对所有对象进行一次扫描,如果该对象不存在引用,则被回收,反之则保存。

    在Lua5.0及其更早的版本中,Lua的GC是一次性不可被打断的过程,使用的Mark算法是双色标记算法(Two color mark),这样系统中对象的非黑即白,要么被引用,要么不被引用,这会带来一个问题:在GC的过程中如果新加入对象,这时候新加入的对象无论怎么设置都会带来问题,如果设置为白色,则如果处于回收阶段,则该对象会在没有遍历其关联对象的情况下被回收;如果标记为黑色,那么没有被扫描就被标记为不可回收,是不正确的。

    为了降低一次性回收带来的性能问题以及双色算法的问题,在Lua5.1后,Lua都采用分布回收以及三色增量标记清除算法(Tri-color incremental mark and sweep)

    
    每个新创建的对象颜色设置为白色
    
    //初始化阶段
    
    遍历root节点中引用的对象,从白色置为灰色,并且放入到灰色节点列表中
    
    //标记阶段
    
    while(灰色链表中还有未扫描的元素):
    
    从中取出一个对象,将其置为黑色
    
    遍历这个对象关联的其他所有对象:
    
    if 为白色
    
    标记为灰色,加入到灰色链表中(insert to the head)
    
    //回收阶段
    
    遍历所有对象:
    
    if 为白色,
    
    没有被引用的对象,执行回收
    
    else
    
    重新塞入到对象链表中,等待下一轮GC
    

    二、GC的数据结构

    分析Lua中对于需要GC的类型数据

    define iscollectable(o) (ttype(o) >= LUA_TSTRING)

    都会有一个基本的定义CommonHeader,其定义为:


    image.png

    next: GCObject链表指针,该指针用来将所有的GC对象都链接在一个表中;

    tt: 数据类型:nil, boolean, number, string...

    marked: 标记字段,byte表示的字段颜色定义为


    image.png

    这儿特定解释一下为什么会有两种白色,前面提到,5.1后的Lua采用的是三色标记算法,其实质是四色标记算法,分为0型白色和1型白色,在GC回收的时候,会设置当前的白色为其中一种,详见globalstate中的currentwhite,这样在代码回收的时候,如果当前对象的白色不为currentwhite,则认为其不可回收,这样的对象需要等到下一次的GC才能决定是否回收,具体参看后面的,会有对应的应用。对于global_state的设计为:


    image.png
    参考《Lua设计与实现》

    相关文章

      网友评论

          本文标题:Lua GC

          本文链接:https://www.haomeiwen.com/subject/omfmtqtx.html