lua GC垃圾收集 内存优化
lua垃圾收集函数:
collectgarbage("collect"): 做一次完整的垃圾收集循环。通过参数 opt 它提供了一组不同的功能:
collectgarbage("count"): 以 K 字节数为单位返回 Lua 使用的总内存数。 这个值有小数部分,所以只需要乘上 1024 就能得到 Lua 使用的准确字节数(除非溢出)。
collectgarbage("restart"): 重启垃圾收集器的自动运行。
collectgarbage("setpause"): 将 arg 设为收集器的 间歇率 (参见 §2.5)。 返回 间歇率 的前一个值。
collectgarbage("setstepmul"): 返回 步进倍率 的前一个值。
collectgarbage("step"): 单步运行垃圾收集器。 步长"大小"由 arg 控制。 传入 0 时,收集器步进(不可分割的)一步。 传入非 0 值, 收集器收集相当于 Lua 分配这些多(K 字节)内存的工作。 如果收集器结束一个循环将返回 true 。
collectgarbage("stop"): 停止垃圾收集器的运行。 在调用重启前,收集器只会因显式的调用运行。
如下工具可以统计lua中的某个文件中某一行带来的内存分配和消耗:
local memory_state = {} -- 储存所有的内存调用 local current_memory = 0 -- 储存总内存状态 local function recordAlloc(event, line_no) local memory_increased = collectgarbage("count") - current_memory if (memory_increased < 1e-6) then return end local info = debug.getinfo(2, "S").source info = string.format("%s@%s", info, line_no - 1) local item = memory_state[info] if not item then memory_state[info] = {info, 1, memory_increased} else item[2] = item[2] + 1 item[3] = item[3] + memory_increased end current_memory = collectgarbage("count") end utilsMemoryLeakDetector = {} function utilsMemoryLeakDetector:StartRecord() if debug.gethook() then self:StopRecord() return end memory_state = {} current_memory = collectgarbage("count") debug.sethook(recordAlloc, "l") end function utilsMemoryLeakDetector:ShowRecord(count) if not memory_state then return end local sorted = {} for k, v in pairs(memory_state) do table.insert(sorted, v) end table.sort(sorted, function(a, b) return a[3] > b[3] end) for i = 1, count do local v = sorted[i] print(string.format("MemoryDump [MEM: %sK] [COUNT: %s ] [AVG: %s k] %s:", v[3], v[2], v[3] / v[2], v[1])) end end function utilsMemoryLeakDetector:EndRecord() debug.sethook() end utilsMemoryLeakDetector:StartRecord() if IsInToolsMode() then Convars:RegisterCommand("debug_dump_lua_memory_detail",function(_, top_count) count = tonumber(top_count) or 30 utilsMemoryLeakDetector:ShowRecord(count) end,"Dump lua usage",FCVAR_CHEAT) end