问题提出
lua的局部变量以及其它置为nil的对象属于垃圾回收的来源
当我创建多个线程的时候,线程中延时多时没问题,延时短时会出现lua报错内存不足的问题。
所以难道lua的内存释放和时间有关系?不是立即回收、指定的时间间隔回收垃圾?
细想频繁的释放回收垃圾确实是会影响执行效率。
通过collectgarbage("count")可查看当前Lua 使用的总内存数,发现值会不断累加,达到某个值后会自动骤减,就是会在某个状态或时间下才执行的垃圾回收。
下文摘自菜鸟教程lua.
垃圾回收器函数
Lua 提供了以下函数collectgarbage ([opt [, arg]])用来控制自动内存管理:
-
collectgarbage("collect"): 做一次完整的垃圾收集循环。通过参数 opt 它提供了一组不同的功能:
-
collectgarbage("count"): 以 K 字节数为单位返回 Lua 使用的总内存数。 这个值有小数部分,所以只需要乘上 1024 就能得到 Lua 使用的准确字节数(除非溢出)。
-
collectgarbage("restart"): 重启垃圾收集器的自动运行。
-
collectgarbage("setpause"): 将 arg 设为收集器的 间歇率。 返回 间歇率 的前一个值。
-
collectgarbage("setstepmul"): 返回 步进倍率 的前一个值。
-
collectgarbage("step"): 单步运行垃圾收集器。 步长"大小"由 arg 控制。 传入 0 时,收集器步进(不可分割的)一步。 传入非 0 值, 收集器收集相当于 Lua 分配这些多(K 字节)内存的工作。 如果收集器结束一个循环将返回 true 。
-
collectgarbage("stop"): 停止垃圾收集器的运行。 在调用重启前,收集器只会因显式的调用运行。
说明:
- collectgarbage("collect") 回收的是整个lua待释放的垃圾,对于多线程创建的lua中需要回收的垃圾同样有效。及回收是全局垃圾。
- 执行一次将主动回收一次。
可设置自动回收的机制,不用主动释放,当然有比较大的空间使用完待回收时,建议主动释放一次。
自动释放设置
当设置了setstepmul和setpause,Lua便会开启自动垃圾回收。
- collectgarbage("setpause", 200) : 内存增大 2 倍(200/100)时自动释放一次内存 (200 是默认值)。
- collectgarbage("setstepmul", 200) :收集器单步收集的速度相对于内存分配速度的倍率,设置 200 的倍率等于 2 倍(200/100)。(200 是默认值)
先记着,没太搞清楚这两个值的具体含义。
测试程序
创建10个线程。FreeRTOS堆栈和lua堆栈是分开的,FreeRTOS给了20k,文件系统FAT用的是FreeRTOS的堆栈,和lua 使用malloc分配,分配了32k。
这几个东西凑起来就52k,都已经在压缩了,加上其他变量,轻轻松松上64k。所以一般内存小的stm32f1跑这几个东西有点力不从心,很限制秀操作,纠结。。。。。。
collectgarbage("collect")
print(collectgarbage("count"))
collectgarbage("setpause", 100)
collectgarbage("setstepmul", 200)
local x = 0
function func(data)
local a = 0
while true do
x = x + 1
a = a + 1
local i
for i = 1, 10000 do
end
local c = task.msg() --自定义获取FreeRTOS剩余堆栈函数
print(data.value .. " " .. a, x, collectgarbage("count"), c)
if a % 10 == 0 then
-- collectgarbage("collect")
end
os.sleep(100)
end
end
for i = 1, 10 do
task.run(func, {value = i})
end
while true do
os.sleep(100)
task.led_on()
os.sleep(100)
task.led_off()
end
运行界面:
lua堆占用空间稳定在20.06k。
其他
collectgarbage("setpause", value) ,当value设置为200时,内存一直在变动,累加到某个值再释放,
设置为100能稳定下来。后续具体研究吧