Я использую проприетарную платформу, которая сообщает об использовании памяти в режиме реального времени на экране. Я решил использовать Class.lua, найденный на http://lua -users.org / wiki / SimpleLuaClasses
Однако я заметил проблемы с памятью при очистке объекта, созданного с помощью простого класса Account. В частности, я хотел бы начать с, скажем, 146 КБ используемой памяти, создать 1000 объектов класса, который просто содержит целочисленную переменную экземпляра и сохранить каждый объект в таблицу.
Используемая память теперь 300k
Затем я бы завершил работу, перебирая таблицу и устанавливая для каждого элемента таблицы значение nil. Но никогда не получу обратно 146k, обычно после этого я оставляю 210k или что-то подобное. Если я выполню последовательность загрузки еще раз во время того же сеанса, она не превысит 300 Кбайт, поэтому это не утечка памяти.
Я попытался создать 1000 целых чисел в таблице и установить их равными nil, что возвращает мне 146 тыс.
Кроме того, я попробовал более простой файл класса (Account2.lua), который не зависит от class.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
Ну, я попробовал приведенный выше код, и кажется, что сборщик мусора ("count") сообщает, что lua возвращает мне всю память во всех трех сценариях.
Вот мои результаты для collectgarbage ('count')
ACC0
- На старте: 25,567K используется
- На нагрузке: 89,334K используется
- При продувке: 25,567K используется
ACC1
- На старте: 25,567K используется
- На нагрузке: 440,567 Кб
- При продувке: 25,567K используется
ACC2
- На старте: 25,327K используется
- На нагрузке: 245,34K используется
- При продувке: 25,327K используется