lua2.1垃圾回收机制

来源:互联网 发布:java中wait用法 编辑:程序博客网 时间:2024/05/18 01:46

 

lua2.1采用的是“标记-清理”的垃圾回收方法,垃圾回收入口函数是lua_pack。

 

这个函数会在两个地方被调用,一个是创建字符串的时候(lua_createstring),

另外一个是创建哈希表的时候(lua_createarray)。这也说明了这两种操作

分配的资源将被列入垃圾回收范围之内。

 

字符串:

在lua中的字符串是一个TaggedString,这个结构中有一个字段叫marked,如果有个TaggedString的marked

字段值为0,那么这个TaggedString对象对应的字符串将在垃圾回收过程中被销毁。

 

哈希表

在lua中用了Hash结构来实现哈希表,这个结构和TaggedString结构一样有一个mark,如果某个Hash

对象中的mark字段不为1,那么将清除这个Hash结构。

 

在字符串和哈希表被从堆中分配出来之后,他们的mark都是0,也就是说如果分配出来之后没有对这个mark置

上一个数字的话(字符串置非0,哈希表置1),他们会在下次垃圾回收的时候被销毁掉。那么什么时候这个

mark会改变呢?通过搜索代码我们可以知道以下情况会导致mark的改变而导致对象不会被回收:

1)对象在栈上

2)对象在全局变量表上

3)对象在一个所谓的“锁对象数组上”(暂且不深究)

 

满足上面3个条件中至少一个的对象在一次垃圾回收之后不会被销毁,因为在回收之前他们的mark字段都会被

置上一个数以阻止他们被销毁。当然在垃圾回收之后他们的mark字段又会被初始化,假设这之后某个对象没有

满足以上3个中任何一个条件,那么在下次垃圾回收的时候将被回收。

*需要注意的是:哈希表的某个key-value对中的value可能是TaggedString或Hash类型,我们称这个哈希表为父对象,

而后面的TaggedString和Hash类型为子对象,子对象会继承父对象的mark字段,这也就意味父对象和子对象的

mark字段是一样的,虽然子对象不在栈或全局变量表或锁对象表上,但是如果它的父对象在的话,那么子对象也不会

被回收掉。

 

算法大致如下:

 

垃圾回收开始

将栈上、全局变量表上和“锁对象数组”上的对象置上阻止其被回收的的标记A(注意子对象)

遍历 字符串链表、哈希表链表:

如果对象的标记是A,那么不回收,并将其标记置为B(允许对象被回收)

如果对象的标记是B,那么回收

垃圾回收结束

 

 

相关的细节:

lua2.1在创建TaggedString和Hash结构的时候都会调用lua_pack,但是并不是每次调用这个函数的

时候都会执行垃圾回收操作,其实这里面还设置了一个上限,我们令这个上限是T,T最初的值为256,

当lua_pack的调用次数C >= T的时候才会进行垃圾回收操作,并且再垃圾回收之后,C会被置0。另外

还有一点需要注意的是T是有可能不断地改变的,这个改变过程也是在一次垃圾回收操作之后发生的。

这里假设在垃圾回收过程中总共回收了R个对象,那个T = MIN(MIN_T, (T * 16 - 7 * R) / 12),其中MIN_T = 10。

 

对于为什么会有这么一个公式,目前我也是查阅相关资料以希望得到答案,如果各位知道的话请不吝赐教!

 

原创粉丝点击