在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
对于内存的管理,是程序在应用的时候的必需知识点,《Lua设计与实现》中对Lua语言的GC原理做了一个详细的讲解,云风的blog也对其进行了详尽的讲解Lua GC 的源码剖析 系列 给出作者 codedump 在github上的lua源码链接:https://github.com/lichuang/Lua-5.1.4-codedump 这儿就继续做《Lua设计与实现》的阅读笔记,对Lua GC原理及其过程做一个详尽的讲解,由于篇幅较大,就一分为二,写上下篇来讲解整个过程。 一、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,其定义为:
next: GCObject链表指针,该指针用来将所有的GC对象都链接在一个表中; tt: 数据类型:nil, boolean, number, string... marked: 标记字段,byte表示的字段颜色定义为
这儿特定解释一下为什么会有两种白色,前面提到,5.1后的Lua采用的是三色标记算法,其实质是四色标记算法,分为0型白色和1型白色,在GC回收的时候,会设置当前的白色为其中一种,详见globalstate中的currentwhite,这样在代码回收的时候,如果当前对象的白色不为currentwhite,则认为其不可回收,这样的对象需要等到下一次的GC才能决定是否回收,具体参看后面的,会有对应的应用。对于global_state的设计为:
具体的参数的作用,详见注释,就不在一一解释了 三、GC的流程 1、数据的创建 想要了解GC的过程,首先看看数据是怎么在创建的时候被链接到GC链表中的,主要分为三种数据的创建 1) 一般数据的创建 luaC_link
简单直接,直接insert to the head 2) upval的创建 luaC_linkupval
3) userdata(udata)的创建 luaS_newdata
2、开始GC 整个GC过程分为五个阶段,其定义为
其执行GC的函数为singlestep,来看第一步的操作: 进一步看看markroot的操作:
其实就是reset一遍相关的变量,然后标记mainthread, G表,registry表,然后切换到下一个标记阶段。 参看定义:
最后都要执行reallymarkobject函数(此处需要展示一下我的竖屏截图便利了:D):
基本的注释都解释了各个对象是如何的处理的,udata是不会引用其他类型的数据,所以一步到黑色,upvalue则根据是否为close来决定是否标记到黑色,open状态的upvalue变化较为频繁,需要在后面的remarkupvals中解决。 写到这儿,已经写很长了,为了阅读的便利,让我们下一篇文章继续GC的进程吧:D |
请发表评论