Lua GC原理分析

Lua5.0及其更早的版本采用的是二色标记法:

  1.root对象组(所有最上层定义的对象)开始遍历,所有可达对象都被标记为黑色。

  2.等遍历完成后,剩余的白色对象即为可回收对象,回收这些白色对象。

  3.重置黑色对象为白色对象,等待下次回收过程。

此算法有明显的缺点,就是每次执行都会把整个虚拟机停下来(Stop the World,所以会有明显的卡顿,为此它采取的策略是:每当内存分配总量超过上次GC后的2倍,就跑一次GC流程。即使如此,再实践中的卡顿问题也很明显,因此5.0之前的lua多用于内嵌脚本,承担小部分工作。

Lua5.1采用三色标记法清理:

白色:在gc开始阶段,所有对象颜色都为白色,如果遍历了一遍之后,对象还是白色的将被清除。
灰色:灰色用在分步遍历阶段,如果一直有对象为灰色,则遍历将不会停止。
黑色:确实被引用的对象,将不会被清除,gc完成之后会重置为白色。

总结一下:

1.从root开始遍历节点,白色节点设为灰色,加入到处理灰色的链表中gray。

2.在gray中继续遍历,发现其下方有子节点,把子节点加入到gray中,并且自己置为黑色。

3.重复1,2步骤直到都遍历完。

4.清理剩余的白色节点,如果产生了节点重新关联则标记为另一种白色节点,此次先跳过

Lua 5.1 GC解决了Stop the World的问题,但是总工作量没有变,依然要遍历全部对象。

为此,在Lua5.2尝试性的引入了分代GCgenerational gc),

       分代GC的产生是基于这样一个假设:大部分对象被分配出来后很快就回收掉了,

在这种情况下,垃圾收集器可以集中精力对付刚刚构造出来的年轻对象,每次收集只处理年轻对象,之后内存增长到一定程度时再全部处理一次。这个思路没错,但是5.2版本提供的分代GC过于简单,任何活过当前收集周期的对象就会变老,实践中会造成很多不该变老的对象迅速变老。因此在Lua5.3中移除了分代GC

       在最新的Lua5.4中,分代GC又被重新设计实现,将原来的一轮变老改成了活过两轮才变老,当前5.4版本中步进式( incremental gc )和分代GC generational gc )同时存在,并可自由切换。

Lua5.4可采用分代式GC:

这里的分代式算法就是上面的三色标记法。

但区别在于,5.1的是gc过后剩下的节点下次gc时还是白色。

而这里是会加入到老年代列表,老年代列表的节点是不会被gc到。这样的好处是下次采用分代式gc不需要全部遍历所有节点,代价就是可能老年代确实存在着一些不需要使用的可回收对象这时候不会回收。这种设计属于经验设计。

这里实际上是二轮老年链表,这里的gc不会被遍历。但有可能因为其下新增了白色节点而被从老年列表里拉出来参入到下一轮的gc。

原理如下:

简单来说,就是这次的gc如果超过设置的值,下次就触发全量gc,如果不是则为分发式gc。这个值是由上面设置的参数决定的。

另附gc使用方法:

参考:lua源码解析——gc实现机制[详细版](一)_lua的gc-CSDN博客

Ierusalimschy.pdf (lua.org)

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值