composer.removeScene with newSnapshot = Memory Leak

Problem: Lua Memory is ever increasing when composer.removeScene is used with any newSnapshots placed into the sceneGroup.

Example: As a test case, consider scene1 and scene2. Each one creates 100 rectangles, puts them into a newSnapshot and adds that to the sceneGroup with:

sceneGroup:insert(snapshot)

The scenes pingpong between each other. With snapshots and composer.removeScene, the lua memory keeps going up and up on each new scene. But with only one of these things e.g. removeScene without snapshots or snapshots but no removeScene then the memory returns to a baseline on each new scene (with a garbage collection).

The following familiar code is from scene1 as it removes scene2. The code is the same on scene2 except it removes scene1.

function scene:create( event ) local sceneGroup = self.view local width, height = display.contentWidth, display.contentHeight local halfW, halfH = width\*0.5, height\*0.5 local bg = display.newRect( halfW, halfH, width, height ) bg:setFillColor( 0.2 ) sceneGroup:insert(bg) -- Add to Snapshot local snapshot = display.newSnapshot( width, height ) math.randomseed( os.time() ) -- Add rect to the screen for i=1,100 do local item = display.newRect( halfW, halfH, halfW, halfH ) item:setFillColor( 1,1,1,0.1 ) -- move to random position in a 200x200 region in the middle of the screen local randX, randY = math.random( -halfW, halfW ), math.random( -halfH, halfH ) item:translate( randX, randY ) -- insert item into snapshot snapshot.group:insert( item ) end sceneGroup:insert(snapshot) snapshot:translate( halfW, halfH ) -- Center snapshot snapshot:invalidate() -- Invalidate snapshot snapshot.alpha = 0.5 -- Apply to flattened image end function scene:show( event ) local sceneGroup = self.view local phase = event.phase local currScene = composer.getSceneName( "current" ) if phase == "will" then elseif phase == "did" then if currScene == "scene1" then if nil~= composer.getScene("scene2") then composer.removeScene("scene2", true) end -- Destroy for previous Scene gets called print("------- call remove Scene\_2 -------") else composer.removeScene("scene1", true) -- Destroy for previous Scene gets called print("------- call remove Scene\_1 -------") end --composer.removeHidden() -- Goto Next scene local goto = timer.performWithDelay(500, function() composer.gotoScene( "scene2", "fade", 250 ) end) end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if event.phase == "will" then timer.performWithDelay(1, function() collectgarbage("collect") end) elseif phase == "did" then end end

Hi @kilopop,

Can you please file a bug report for this so we can investigate and track it?

Thanks,

Brent

Thanks Brent. I have submitted the bug some hours ago. I have yet to receive an email from the automated bug tracking system containing a case number. Is this normal?

Hi @kilopop,

I’m not finding the report as filed. Can you .zip up your test case file and send it to support [at] coronalabs [dot] com.

Thanks,

Brent

Sure will do, thanks.

This is the Case number: #6559998.

It’s been 10 days. What is the average time to squash bugs?

Been a couple of months, still no word…

An update, noticed snapshots are not being disposed even after normal display.remove of objects and and also unrequire of a module containing said snapshot.

We have an app to release that is filled with snapshots that contributing greatly to memory that continues to go up to eventually crash the app. 

I’ll see what I can find out.

Rob

Hi Rob. It’s been a while, did you find out anything?

Hi @kilopop,

This probably is the most obvious question ever, but I assume you also tested removal of the snapshot object itself (display.remove()) after you removed the objects that were contained within it? And doing so still resulted in a memory leak?

Brent

If you see the example above, the snapshot object is inserted into self.view and therefore should be destroyed/disposed by Composer, correct?

Hi @kilopop,

Can you please file a bug report for this so we can investigate and track it?

Thanks,

Brent

Thanks Brent. I have submitted the bug some hours ago. I have yet to receive an email from the automated bug tracking system containing a case number. Is this normal?

Hi @kilopop,

I’m not finding the report as filed. Can you .zip up your test case file and send it to support [at] coronalabs [dot] com.

Thanks,

Brent

Sure will do, thanks.

Hello.
I know that it’s quite old post but I’m also encountered this issue.
I measure memory using **collectgarbage(“count”) **and see that it only increases over time

Not sure if I need to create separate bug report for this

Hi Benzeliden. I can say Brent’s suggestion to remove the snapshot  after  you remove the objects that are contained within it does work. But this seems like a work-around given the snapshot is an object in another group that is itself disposed. Snapshots then do not behave like other display objects in this regard.

Well, removing snapshot doesn’t work. The only thing that works for me is to remove every object in snapshot.group manually

I prepare sample code:

local function createSnapshot(parent) local snapshot = display.newSnapshot(parent, 60 , 60) local rectLeft = display.newRect(5, 10, 10, 20) rectLeft:setFillColor( 1,0,0 ) snapshot.group:insert(rectLeft) local rectCenter = display.newRect(15, 10, 10, 20) rectCenter:setFillColor( 0,1,0 ) snapshot.group:insert(rectCenter) local rectRight = display.newRect(25, 10, 10, 20) rectRight:setFillColor( 0,1,1 ) snapshot.group:insert(rectRight) snapshot.x = display.contentCenterX + math.random(-100, 100) snapshot.y = display.contentCenterY + math.random(-100, 100) return snapshot end local function formatUsage(value) if (value \< 1e3) then return value .. " Kb" end value = value / 1024 return value .. " Mb" end local function PrintMemoryUsage() local usage = system.getInfo( "textureMemoryUsed" ) / 1024 -- to Kb local memUsed = collectgarbage("count") print("texture memory used", formatUsage(usage)) print("system memory used", formatUsage(memUsed)) end local function createSnapshotGroup() local count = math.random(200, 300) local parent = display.newGroup() local snapshots = {} for i = 1, count do snapshots[i] = createSnapshot(parent) end timer.performWithDelay(1400, function() for i = 1, #snapshots do parent:removeSelf() local snapshotToRemove = snapshots[i] snapshotToRemove:removeSelf() --uncomment this lines to prevent memory leak --for j = snapshotToRemove.group.numChildren, 1, -1 do -- snapshotToRemove.group[j]:removeSelf() --end end PrintMemoryUsage() collectgarbage("collect") end) end timer.performWithDelay(1500, createSnapshotGroup, -1)

You can put it into main.lua and run - see memory output in console.

From documentation
 

The snapshot group behaves just like a normal group except:

  • This group cannot be inserted into another group.
  • This group cannot be removed, for example via removeSelf().
  • This group has no parent. - so this probably means that group childs will never be removed automatically

This is the Case number: #6559998.

It’s been 10 days. What is the average time to squash bugs?

Been a couple of months, still no word…

An update, noticed snapshots are not being disposed even after normal display.remove of objects and and also unrequire of a module containing said snapshot.

We have an app to release that is filled with snapshots that contributing greatly to memory that continues to go up to eventually crash the app.