Note that there are some explanatory texts on larger screens.

plurals
  1. POLua metatable Objects cannot be purge from memory?
    primarykey
    data
    text
    <p>I'm using a proprietary platform that reported memory usage in realtime on screen. I decided to use a Class.lua I found on <a href="http://lua-users.org/wiki/SimpleLuaClasses" rel="nofollow noreferrer">http://lua-users.org/wiki/SimpleLuaClasses</a></p> <p>However, I noticed memory issues when purging object created by this using a simple Account class. Specifically, I would start with say 146k of memory used, create 1000 objects of a class that just holds an integer instance variable and store each object into a table. The memory used is now 300k</p> <p>I would then exit, iterating through the table and setting each element in the table to nil. But would never get back the 146k, usually after this I am left using 210k or something similar. If I run the load sequence again during the same session, it does not exceed 300k so it is not a memory leak.</p> <p>I have tried creating 1000 integers in a table and setting these to nil, which does give me back 146k.</p> <p>In addition I've tried a simpler class file (Account2.lua) that doesn't rely on a class.lua. This still incurs memory fragmentation but not as much as the one that uses Class.lua</p> <p>Can anybody explain what is going on here? How can I purge these objects and get back the memory?</p> <p>here is the code --------Class.lua------</p> <pre><code> -- 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 </code> </pre> <p>--------Account.lua------</p> <pre><code> --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) </code></pre> <p>--------Account2.lua------</p> <pre><code> local account2 = {} account2.classname = "unnamed" account2.balance = 2097 -----------Constructor 1 do local metatable = { __index = account2; } function Account2() return setmetatable({}, metatable); end end </code></pre> <p>--------Main.lua------</p> <pre><code> 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. </code></pre> <hr> <p>--Update I've updated the code with suggestions from comments below, and will post my findings later today.</p> <hr> <p>--Update 2 Well I've tried the above code, and it does seem collectgarbage("count") reports lua giving me back all the memory in all three scenarios. Here are my results for collectgarbage('count')</p> <p>ACC0 - On start: 25.567K used - On Load: 89.334K used - On Purge: 25.567K used</p> <p>ACC1 - On start: 25.567K used - On Load: 440.567k used - On Purge: 25.567K used</p> <p>ACC2 - On start: 25.327K used - On Load: 245.34K used - On Purge: 25.327K used</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload