Memory Leak Problem

Hey guys,

I recognized some memory issues at my current project and I was able to reduce the problem to a few lines.

local object = {} function object:createGraphic() local graphic = display.newRect(200,200,11,11) self.graphic = graphic end function object:deleteGraphic() local graphic = self.graphic graphic:removeSelf() graphic=nil self.graphic=nil end

I’m building a tilebased game and every tile is represented by a table which holds all functions and the graphic object.

The tile has functions to create and remove the graphic object, but every time I create and remove the graphic object I got a small memory leak which is climbing up.

It might not be notable with a single tile, but imagine around 1000 tiles creating and removing over and over again, then it becomes a real problem.

So, is there anything wrong with the code above? Am I complitly blind?

I hope you guys could help me out with that.

Greetings

Torben

Hi Torben,

It seems like it’s at least partly (mostly) a funky timing issue with when the garbage collector runs vs. the Corona frame loop mechanism.  If you run this code, you’ll see Lua memory usage constantly climbing with apparently no memory being reclaimed when the object is deleted.  And yet the very last memory print (which runs in the next frame loop due to the 1 millisecond delay) shows a drop in Lua memory almost back to the starting point.  The extra residual usage might have something to do with any memory required by the timer itself.

[lua]

local object = {}

local printMemory = function()

    collectgarbage()

    print("Lua Memory: " … collectgarbage(“count”) … "  Texture Memory: " … system.getInfo(“textureMemoryUsed”))

end

function object:createGraphic()

    local graphic = display.newRect(200,200,11,11)

    self.graphic = graphic

end

function object:deleteGraphic()

    local graphic = self.graphic

    

    graphic:removeSelf()

    graphic=nil

    self.graphic=nil

end

for i=1,100 do

    object:createGraphic()

    printMemory()

    object:deleteGraphic()

    printMemory()

end

timer.performWithDelay(1, printMemory)

[/lua]

  • Andrew

Hi Andrew,

thank you very much, it explains a part of the memory issues.

BUT even when I use the following code (nearly the same then the one you posted, only diffrent order),

the problem stil remains.

I got 108kb from the first “printMemory” and 150kb from the second after the timer.

And this is for 1000 loops, it still goes up when I go for more loops.

Any suggestions about that?

local printMemory = function() collectgarbage() print("Lua Memory: " .. collectgarbage("count") .. " Texture Memory: " .. system.getInfo("textureMemoryUsed")) end local object = {} function object:createGraphic() local graphic = display.newRect(200,200,11,11) self.graphic = graphic end function object:deleteGraphic() local graphic = self.graphic graphic:removeSelf() graphic=nil self.graphic=nil end printMemory() for i=1,1000 do object:createGraphic() object:deleteGraphic() end timer.performWithDelay(1, printMemory)

Hi Torben,

Unfortunately I don’t have a solution there.  I remember this came up once before in another thread a few months ago (I just searched for it but couldn’t find it), and we weren’t able to get to the bottom of it at the time.

But I think I found the solution, as it seems there wasn’t needed one.

Because when you change the code as following:

local printMemory = function() collectgarbage("collect") print("Lua Memory: " .. collectgarbage("count") .. " Texture Memory: " .. system.getInfo("textureMemoryUsed")) end local object = {} function object:createGraphic() local graphic = display.newRect(200,200,11,11) self.graphic = graphic end function object:deleteGraphic() local graphic = self.graphic graphic:removeSelf() graphic=nil self.graphic=nil end local function create() for i=1,10000 do object:createGraphic() object:deleteGraphic() end end create() timer.performWithDelay(1, printMemory) timer.performWithDelay(100, create) timer.performWithDelay(101, printMemory)

Then you notice that there is no difference between the first call of “printMemory” and second. It looks like Corona stores some memory for every display object deleted, but this memory isn’t really occupied. If you create new display objects, that stored memory is reused for the new objects.

I don’t know if thats right, but that’s how I explain it.

So, so much for that and thanks again Andrew

Hi Torben,

It seems like it’s at least partly (mostly) a funky timing issue with when the garbage collector runs vs. the Corona frame loop mechanism.  If you run this code, you’ll see Lua memory usage constantly climbing with apparently no memory being reclaimed when the object is deleted.  And yet the very last memory print (which runs in the next frame loop due to the 1 millisecond delay) shows a drop in Lua memory almost back to the starting point.  The extra residual usage might have something to do with any memory required by the timer itself.

[lua]

local object = {}

local printMemory = function()

    collectgarbage()

    print("Lua Memory: " … collectgarbage(“count”) … "  Texture Memory: " … system.getInfo(“textureMemoryUsed”))

end

function object:createGraphic()

    local graphic = display.newRect(200,200,11,11)

    self.graphic = graphic

end

function object:deleteGraphic()

    local graphic = self.graphic

    

    graphic:removeSelf()

    graphic=nil

    self.graphic=nil

end

for i=1,100 do

    object:createGraphic()

    printMemory()

    object:deleteGraphic()

    printMemory()

end

timer.performWithDelay(1, printMemory)

[/lua]

  • Andrew

Hi Andrew,

thank you very much, it explains a part of the memory issues.

BUT even when I use the following code (nearly the same then the one you posted, only diffrent order),

the problem stil remains.

I got 108kb from the first “printMemory” and 150kb from the second after the timer.

And this is for 1000 loops, it still goes up when I go for more loops.

Any suggestions about that?

local printMemory = function() collectgarbage() print("Lua Memory: " .. collectgarbage("count") .. " Texture Memory: " .. system.getInfo("textureMemoryUsed")) end local object = {} function object:createGraphic() local graphic = display.newRect(200,200,11,11) self.graphic = graphic end function object:deleteGraphic() local graphic = self.graphic graphic:removeSelf() graphic=nil self.graphic=nil end printMemory() for i=1,1000 do object:createGraphic() object:deleteGraphic() end timer.performWithDelay(1, printMemory)

Hi Torben,

Unfortunately I don’t have a solution there.  I remember this came up once before in another thread a few months ago (I just searched for it but couldn’t find it), and we weren’t able to get to the bottom of it at the time.

But I think I found the solution, as it seems there wasn’t needed one.

Because when you change the code as following:

local printMemory = function() collectgarbage("collect") print("Lua Memory: " .. collectgarbage("count") .. " Texture Memory: " .. system.getInfo("textureMemoryUsed")) end local object = {} function object:createGraphic() local graphic = display.newRect(200,200,11,11) self.graphic = graphic end function object:deleteGraphic() local graphic = self.graphic graphic:removeSelf() graphic=nil self.graphic=nil end local function create() for i=1,10000 do object:createGraphic() object:deleteGraphic() end end create() timer.performWithDelay(1, printMemory) timer.performWithDelay(100, create) timer.performWithDelay(101, printMemory)

Then you notice that there is no difference between the first call of “printMemory” and second. It looks like Corona stores some memory for every display object deleted, but this memory isn’t really occupied. If you create new display objects, that stored memory is reused for the new objects.

I don’t know if thats right, but that’s how I explain it.

So, so much for that and thanks again Andrew