[Lua]Lua内存泄露检测原理
lua内存泄露首先第一点,lua中的内存泄露和我们所说的c/c++中的内存泄露本质上是不一样的。 lua中有垃圾回收机制(GC),所以理论上是不会有内存泄露的。当它进行GC的时候,会从根部开始扫描所有的对象,如果某个地方对这个对象还有引用,就不会把这个对象内存collect,这个对象就没有被GC。所以lua中的内存泄露是指那些:已经没有被使用了,但外部依然还有引用存在的对象。 --函数中应该被申明为local的对象忘记加local local function test() testTable = {} --这个testTabel会被存放在全局表_G中,GC时由于此对象还有引用存在,所以这里总是会有一个table泄露。 local mt = {} --mt加了local修饰,函数调用完后,引用也不复存在了,GC时会被回收。 setmetatable(testTable,mt) end 检测原理lua中支持垃圾回收机制的对象有五种:string,table,function,full?userdata,thread。而他们的引用直接或间接的保存到:lua_state对象,_G全局表,Registry注册表,global_state->mt中。 在脚本中:
所以我们就可以在脚本层次实现内存泄露的检测模块。 在搜索时需要注意的几点:
搜索流程图(_G表)? 在检测泄露之前,先搜索一下所有的对象,保存好起始的内存状态,在程序执行之后执行几次GC操作,然后再进行一次搜索,对比两次的结果,多出来的那些就有可能是内存泄露了。? 补充: lua中有一种叫weak表的东东,它的metatable中的__mode被设置为“k","v"或者”kv",表示保存在它中的键或值或键值都是一种弱引用状态。 所以我们可以用另外一种实现:就是把用户自己创建的资源对象统统都丢到weak表中,运行完程序后强制GC,然后去查看weak表,若表中还保存着那个对象,就意味着这个对象还有外部引用(相对弱引用我们就叫它为强引用吧),资源没有被GC掉,所以我们可以说这个对象很有可能是内存泄露了。? Lua垃圾回收算法?Lua的GC算法使用的所谓“Mark?And?Sweep”算法。简单的理解,这个算法将GC分为两个阶段,一个是标记(mark)阶段,这一阶段将所有系统中引用的对象都逐一标记;而在清理(sweep)阶段,将把在mark阶段中没有被标记的数据删除。 在Lua中,使用几种颜色来区分不同的结点:
垃圾收集器函数collectgarbage函数提供了多项功能:停止垃圾回收,重启垃圾回收,强制执行一次回收循环,强制执行一步垃圾回收,获取Lua占用的内存,以及两个影响垃圾回收频率和步幅的参数。collectgarbage(opt,[,arg])
? function test1() collectgarbage("collect")--为了有干净的环境,先把可以收集的垃圾收集了 collectgarbage()--为了保证内存的收集的相对干净,及内存的稳定,要执行多次收集 print("now,Lua内存为:",collectgarbage("count")) -->205.7158203125 KB local colen = {} --现在是局部变量 for i=1,5000 do table.insert(colen,{}) end print("now,collectgarbage("count"))-->860.4111328125 KB --创建5000个table,内存增加了655 KB end function collect1() print("now,collectgarbage("count"))-->608.060546875 KB collectgarbage() collectgarbage() print("now,collectgarbage("count"))-->204.8408203125 KB --最后与一开始只差只有1KB end function test2() collectgarbage("collect")--为了有干净的环境,先把可以收集的垃圾收集了 collectgarbage()--为了保证内存的收集的相对干净,及内存的稳定,要执行多次收集 print("now,collectgarbage("count")) -->205.7158203125 KB colen = {} --现在是全部变量 for i=1,collectgarbage("count"))-->619.826171875 KB --创建5000个table,内存增加了414 KB;这些增加的内存,由于已放到了全局函数中,是永远没有机会被回收到了! end function collect2() print("now,collectgarbage("count"))-->596.7822265625 KB collectgarbage() collectgarbage() collectgarbage() print("now,collectgarbage("count"))-->489.189453125 KB --最后内存增加了284KB(489-205) end 垃圾回收器有两个参数用于控制它的节奏: 第一个参数,称为暂停时间,控制回收器在完成一次回收之后和开始下次回收之前要等待多久; 第二个参数,称为步进系数,控制回收器每个步进回收多少内容。粗略地来说,暂停时间越小、步进系数越大,垃圾回收越快。这些参数对于程序的总体性能的影响难以预测,更快的垃圾回收器显然会浪费更多的CPU周期,但是它会降低程序的内存消耗总量,并可能因此减少分页。只有谨慎地测试才能给你最佳的参数值。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |