LuaGC

本文详细介绍了Lua垃圾回收的发展历程,从Lua5.0的全量GC到Lua5.4的分代模式。讨论了各版本中GC的优缺点,如5.1的步进式GC减少停顿时间,5.2的分代GC导致内存开销,5.3移除分代,以及5.4如何改进分代模式以减少停顿。同时,探讨了垃圾收集器的控制函数,如`collectgarbage`,并分享了实操中调整GC参数对性能影响的经验。
摘要由CSDN通过智能技术生成

目录

一 Lua垃圾回收发展历程

1 Lua5.0及以前-全量GC

2 Lua5.1-步进式GC(增量模式)

3 Lua5.2-分代GC(试验特性)

4 Lua5.3-移除5.2的分代GC

5 Lua5.4-分代模式(经历两个次级收集周期才会变老)

二 垃圾收集器函数

三  实操

参考资料


一 Lua垃圾回收发展历程

1 Lua5.0及以前-全量GC

使用一个非常简单的标记扫描算法。从根集开始遍历对象,把能遍历到的对象标记为活对象,然后再遍历通过分配器分配出来的对象全集链表,把没有标记为活对象的其它对象都删除。

自动GC的默认发生时间:2倍于上次GC后的内存使用量。

缺点: stop the world,会卡住所有操作,直到gc完成。

2 Lua5.1-步进式GC(增量模式)

实现了一个步进式垃圾收集器(增量标记-扫描收集器),会在虚拟机的正常指令逻辑间交错分步运行,尽量把每步的执行时间减到合理的范围。(每个GC周期在程序执行交织的小步中执行标记清除扫描)

采用了一种三色标记的算法。每个对象都有三个状态,无法被访问到的对象是白色,可访问到,但没有递归扫描完全的对象是灰色,完全扫描过的对象是黑色。

步进式GC工作流程:GC的步进和真实时间无关,只和虚拟机分配新的内存有关。即只要虚拟机不分配更多内存,GC不会自动运行。

GC依靠新增内存量来决定该做多少工作,也依靠标记或清理的内存量来决定工作做了多少。

每次做的多了,会导致程序更多额外的停顿,做少了,会导致内存回收速度赶不上新增速度。

分析:能减少每次GC工作时的停顿时间,但无法减少GC带来的额外开销,时间成本和空间成本相比全量GC增加了。

每个周期都需要遍历所有的对象,当内存达到一定量级时(比如10G),这时候遍历的开销还是相当大的。

3 Lua5.2-分代GC(试验特性)

只针对单个次级收集周期处理。任何对象活过当前的收集周期,就会变老。

缺点:例如一个对象刚刚被创建出来,次级收集周期就开启了,很容易就活过这个周期(eg:函数尚未返回,刚在堆栈上创建出来的对象就不能被回收),变成老对象。

这种本该被次级收集回收的对象未被回收,造成内存开销。

4 Lua5.3-移除5.2的分代GC

5 Lua5.4-分代模式(经历两个次级收集周期才会变老)

在分代模式下,收集器频繁执行次要收集(仅遍历最近创建的对象),如果在次要收集之后使用的内存仍然超出限制,则收集器进行一次stop-the-world(阻断的)主要收集。(遍历所有对象)

主要使用两个参数:次要乘数和主要乘数。(参数含义见下文垃圾收集器函数)

分代GC可以更及时的回收内存基于这样的假设:大部分对象被分配出来后很快就回收掉了。

把对象分为青年和老年的两代,新创建出来的对象一律归为青年代,一旦青年对象经历了两轮收集周期还未被回收,就成为老年对象。

在每个次级收集周期,收集器只对青年代对象进行遍历清除工作,这样就避免了每次都遍历大量并不活跃却长期存活的老年对象,又可以及时清理掉大量生命周期短暂的青年对象。

次级收集周期越密集,单个周期内的青年对象就越少,需要做的工作也越少,停顿时间也就缩小了。=>可以更及时的回收内存

分析:分代GC的一个问题是进入主收集周期,必须做一次完整的标记清除,和Lua5.0的全量GC是一样的,会带来停顿问题。

 

二 垃圾收集器函数

Lua提供了以下函数collectgarbage ([opt [, arg]])控制自动内存管理:

(Lua5.1&#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值