Lua GC 机制
02 Apr 2022垃圾回收
Lua 垃圾是自动回收的,但是也提供了 API 用于手动控制回收时机,在合适的时候手动调用 GC,较为平缓的控制内存占用。
调用 collectgarbage([opt [, art]])
控制 GC,opt有
- “collect” 直接开始一次完整的 GC。它是默任的 opt
- “stop” 停止自动 GC
- “restart” 重新开始自动 GC
- “count” 获得当前 Lua 使用的所有内存占用,单位k
- “step” 分步进行 GC,arg 为步数,当本次步数可完整 GC 则返回 true。其实我没搞懂
- “setpause” 设置 GC 的触发内存占用。以 100 为 1 倍,当设为 arg = 200 时,GC 的触发条件是当前占用内存达到上次 GC 后占用内存的两倍,数值越大, GC 频率越低,设置小于 100 会立即进行 GC 。使用该参数会返回上次设置的触发值
- “setstepmul” 设置 GC 的触发速度(相对内存申请速度而言)。以100为1倍,当设为 arg = 200 时,GC 的执行频率是内存申请的两倍,数值越大,GC 触发频率越高,不要设置小于 100 会永远无法完成 GC。详细看示例
注:”setpause” 和 “setsetpmul” 共同控制着 GC 频率
示例
local function Func( )
local a = {}
for i = 1, 1000 do
table.insert(a, i)
end
end
collectgarbage("collect")
collectgarbage("setstepmul", 200)
print("count-size : " .. collectgarbage("count"))
local previous = collectgarbage("setpause", 200)
print("begin")
for i = 1, 8 do
Func()
print("count-size ".. i .." : " .. collectgarbage("count"))
end
print("end")
print("count-size : " .. collectgarbage("count"))
输出
count-size : 20.3857421875
begin
count-size 1 : 37.1953125
count-size 2 : 53.3115234375
count-size 3 : 69.43359375
count-size 4 : 37.009765625
count-size 5 : 53.1298828125
count-size 6 : 69.251953125
count-size 7 : 37.0107421875
count-size 8 : 53.1328125
end
count-size : 53.2177734375
可以初始有用到的内存大致占用 20kb,并从增长速率可以看出,每次 Func() 循环会产出 16kb 左右 garbage。设置collectgarbage("setpause", 200)
后,根据说明,应该在 40kb 的时候触发一次 GC,但是似乎 GC 并没有很符合预期。在 53kb 后,再次提升为 69kb。第二次的循环就会让内存占用超过到 40kb,没有进行 GC 可以理解为申请内存时先判断是否超过设定值,37kb 时没有超过,所以又一次申请了 16kb 内存。但为什么还会出现 69kb 的情况呢,原因就在collectgargage("setstepmul", 200)
上,200 速度太低了。当设置为 900 后,可获得
count-size : 20.4013671875
begin
count-size 1 : 37.2109375
count-size 2 : 53.3271484375
count-size 3 : 37.02734375
count-size 4 : 53.1455078125
count-size 5 : 37.02734375
count-size 6 : 53.1455078125
count-size 7 : 37.02734375
count-size 8 : 53.1455078125
end
count-size : 20.99609375
Get~