Lua ——垃圾回收

垃圾回收

  Lua语言使用自动内存管理。通过垃圾收集自动删除成为垃圾的对象。

Lua中主要的辅助垃圾收集器的机制有:

  • 弱引用表 (weak table)
  • 析构器 (finalizer)
  • 函数 collectgarbage

弱引用表允许Lua收集被程序访问的对象,但是数字和布尔不会被回收;

析构器允许收集不在垃圾收集器控制下的外部对象;

函数 collectgarbage 允许手动控制垃圾收集器的步长

弱引用表

一个表是否为弱引用表是由其元表中的 __mode控制。

如果该字段值为"k", 那么这个表的键为弱引用

如果该字段值为"v",那么这个表的值为弱引用

如果该字段值为"kv",那么这个表的键和值都为弱引用

__mode模式为 “k”

表示弱引用表的键为弱引用,当键被覆盖,可以被回收

local weaktable={}
local metable ={
    __mode ="k"
}
--这里tab就是返回的weaktable
local tab = setmetatable(weaktable,metable)

local table1={}
weaktable[table1]=5

--当打开这里的注释后,需要给collectgarbage()方法添加上注释,会发现弱引用表里面的值被回收
-- for key, value in pairs(weaktable) do
--     print(key,value)
-- end

--将键置为nil,弱引用表中就会回收它
table1=nil
print("--------------")

collectgarbage()

for key, value in pairs(weaktable) do
    print(key,value)
end
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
__mode 模式为"v"

表示弱引用表的值为弱引用,当值置nil,可以被回收

略微修改上面的案例:

local weaktable={}
local metable ={
    __mode ="v"
}
--这里tab就是返回的weaktable
local tab = setmetatable(weaktable,metable)

local table1={}
weaktable[5]=table1

--当打开这里的注释后,需要给collectgarbage()方法添加上注释,会发现弱引用表里面的值被回收
-- 当然,是否被回收都不影响置为nil后,weaktable长度变成0
-- for key, value in pairs(weaktable) do
--     print(key,value)
-- end

table1 = nil

collectgarbage()

for key, value in pairs(weaktable) do
    print(key,value)
end
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
__mode模式为"kv"

案例可参考上面的"k"和"v",作用就是上面作用的叠加,详细过程略。

总结

  至于为什么键和值必须是引用类型(例如用表作为键或者值)才能让弱引用表的回收功能生效,为什么是数字类型或者布尔类型无法生效,值得深入研究,这里只写了结论,不再深究。

析构器

__gc元方法,对象释放时的操作,垃圾回收后占用内存变小

local ob={"hello"}
local oj={ob,}
local metable={
    __gc=function (ob)
        print("-------gc-------")
        for key, value in pairs(ob) do
            print(key,value)
        end
        print("----------------")
    end
}

setmetatable(ob,metable)

ob=nil
-- 垃圾回收前
print(collectgarbage("count"))
-- 执行垃圾回收
collectgarbage()
-- 垃圾回收后
print(collectgarbage("count"))

--输出,可以看到占用内存变小了
25.1328125
24.1923828125
-------gc-------
1	hello
----------------
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
函数 collectgarbage

控制垃圾收集的步长。

通过collectgarbage对垃圾收集器进行一些特别的操作。

collect

强制进行垃圾回收,这个是默认值。例如:

collectgarbage("collect")
  • 1.
count

返回当前的Lua内存使用情况。例如:

local count = collectgarbage("count") print("Memory usage:", count, "KB")
  • 1.
stop

暂停垃圾回收器。例如:

collectgarbage("stop")
  • 1.
restart

重新启用垃圾回收器。例如:

collectgarbage("restart")
  • 1.
setpause

设置垃圾回收器的暂停比例。例如:

collectgarbage("setpause", 200)
  • 1.
setstepmul

设置垃圾回收器的运行速度相对于内存分配速度的倍数。例如:

collectgarbage("setstepmul", 1000)
  • 1.
step

设置step参数为一个正整数表示垃圾回收器工作的步数,垃圾回收器将进行n个步骤的工作

collectgarbage("step", n)
  • 1.

设置step参数为一个负整数表示垃圾回收器工作直到回收所有未使用的内存,垃圾回收器将工作直到回收了至少n字节的内存,或者无法再进行垃圾回收为止

collectgarbage("step", -n)
  • 1.

设置step参数为0表示垃圾回收器不进行完整的垃圾回收过程,只以最小步长来执行。

collectgarbage("step", 0)
  • 1.