我正在使用专有平台,在屏幕上实时报告内存使用情况。我决定使用我在http://lua-users.org/wiki/SimpleLuaClasses
上找到的Class.lua但是,我注意到使用简单的Account类清除由此创建的对象时的内存问题。具体来说,我首先要说使用146k的内存,创建一个只包含整数实例变量的类的1000个对象,并将每个对象存储到一个表中。 使用的内存现在是300k
然后我会退出,遍历表并将表中的每个元素设置为nil。但是永远不会得到146k,通常在此之后我会使用210k或类似的东西。如果我在同一个会话期间再次运行加载序列,它不会超过300k,因此它不是内存泄漏。
我尝试在表格中创建1000个整数并将它们设置为nil,这确实给了我146k。
此外,我尝试了一个不依赖于class.lua的简单类文件(Account2.lua)。这仍然会导致内存碎片,但不会像使用Class.lua
那样多有人可以解释这里发生了什么吗?如何清除这些物体并取回记忆?
这是代码 -------- Class.lua ------
-- class.lua
-- Compatible with Lua 5.1 (not 5.0).
--http://lua-users.org/wiki/SimpleLuaClasses
function class(base,ctor)
local c = {} -- a new class instance
if not ctor and type(base) == 'function' then
ctor = base
base = nil
elseif type(base) == 'table' then
-- our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._base = base
end
-- the class will be the metatable for all its objects,
-- and they will look up their methods in it.
c.__index = c
-- expose a ctor which can be called by ()
local mt = {}
mt.__call = function(class_tbl,...)
local obj = {}
setmetatable(obj,c)
if ctor then
ctor(obj,...)
else
-- make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj,...)
end
end
return obj
end
c.init = ctor
c.instanceOf = function(self,klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c,mt)
return c
end
-------- Account.lua ------
--Import Class template
require 'class'
local classname = "Account"
--Declare class Constructor
Account = class(function(acc,balance)
--Instance variables declared here.
if(balance ~= nil)then
acc.balance = balance
else
--default value
acc.balance = 2097
end
acc.classname = classname
end)
-------- Account2.lua ------
local account2 = {}
account2.classname = "unnamed"
account2.balance = 2097
-----------Constructor 1
do
local metatable = {
__index = account2;
}
function Account2()
return setmetatable({}, metatable);
end
end
-------- Main.lua ------
require 'Account'
require 'Account2'
MAX_OBJ = 5000;
test_value = 1000;
Obj_Table = {};
MODE_ACC0 = 0 --integers
MODE_ACC1 = 1 --Account
MODE_ACC2 = 2 --Account2
TEST_MODE = MODE_ACC0;
Lua_mem = 0;
function Load()
for i=1, MAX_OBJ do
if(TEST_MODE == MODE_ACC0 )then
table.insert(Obj_Table, test_value);
elseif(TEST_MODE == MODE_ACC1 )then
table.insert(Obj_Table, Account(test_value)); --Account.lua
elseif(TEST_MODE == MODE_ACC2 )then
table.insert(Obj_Table, Account2()); --Account2.lua
Obj_Table[i].balance = test_value;
end
end
end
function Purge()
--metatable purge
if(TEST_MODE ~= MODE_ACC0)then
--purge stage 0:
print("set each elements metatable to nil")
for i=1, MAX_OBJ do
setmetatable(Obj_Table[i], nil);
end
end
--purge stage 1:
print("set table element to nil")
for i=1, MAX_OBJ do
Obj_Table[i] = nil;
end
--purge stage 2:
print("start table.remove...");
for i=1, MAX_OBJ do
table.remove(Obj_Table, i);
end
print("...end table.remove");
--purge stage 3:
print("create new object_table {}");
Obj_Table= {};
--purge stage 4:
print("collectgarbage('collect')");
collectgarbage('collect');
end
--Loop callback, called every tick
function OnUpdate()
Lua_mem = collectgarbage('count');
collectgarbage('collect');
end
--Loop rendering callback
function OnRender()
DrawText(Lua_mem );
end
-------------------
--NOTE:
--code starts in idle awaiting input from user
--On first input, runs Load(), on exit runs Purge()
--Where DrawText() draws the string parameter passed, to screen.
- 更新 我已根据以下评论中的建议更新了代码,并将在今天晚些时候发布我的调查结果。
- 更新2 好吧,我已经尝试了上面的代码,它看起来似乎收集垃圾(“计数”)报告lua给了我所有三种情况下的所有内存。 以下是我对collectgarbage('count')的结果
ACC0 - 开始时:使用25.567K - 在负载时:使用89.334K - 关于清除:使用25.567K
ACC1 - 开始时:使用25.567K - 负载:使用440.567k - 关于清除:使用25.567K
ACC2 - 开始时:使用25.327K - 负载:使用245.34K - 关于清除:使用25.327K
答案 0 :(得分:2)
您需要强制垃圾收集器回收内存(请参阅collectgarbage("collect")
)。
答案 1 :(得分:1)
<强> Main.lua 强>:
--purge stage 0:
print("set each elements metatable to nil")
for i=1, MAX_OBJ do
setmetatable(Obj_Table[i], nil);
end
根据documentation of Lua,您无法通过尝试将其设置为nil来重置表metatable。它只等于函数getmetatable()
。因此,对象不断被链接。
答案 2 :(得分:1)
大多数动态语言并没有真正将内存释放回系统,而是为将来的分配做好准备。在Lua报告内存减少后尝试创建一些对象 - Lua应该使用它保留给自己的这个释放的内存,平台内存消耗不会增加。