Removing groups that contain groups

Hey, so I’ve been combing through my code recently, trying to iron out some lingering memory leaks. I’ve noticed a peculiarity regarding display groups.

I made a test scenario like this:

local bigGroup = display.newGroup()  
  
local subGroup1 = display.newGroup()  
local subGroup2 = display.newGroup()  
local subGroup3 = display.newGroup()  
  
bigGroup:insert(subGroup1)  
bigGroup:insert(subGroup2)  
bigGroup:insert(subGroup3)  

I then created some display objects and inserted them into the three sub-groups. Now here’s the interesting part… It has been my understanding that removing a group will remove itself and all it’s children (including other groups) so I tested it.

First scenario:

local function removeAll()  
  
 display.remove(bigGroup)  
 bigGroup = nil  
end  
  
timer.performWithDelay(6000, removeAll, 1)  

Everything seemed to work. All my display objects went away and my memUsage after this removeAll() function was around 119kb. But I wasn’t confident this was the best way so I tried it again, this time removing the three sub-groups first.

Second scenario:

local function removeAll()  
 display.remove(subGroup1)  
 subGroup1 = nil  
 display.remove(subGroup2)  
 subGroup2 = nil  
 display.remove(subGroup3)  
 subGroup3 = nil  
  
 display.remove(bigGroup)  
 bigGroup = nil  
end  
  
timer.performWithDelay(6000, removeAll, 1)  

So this should effectively do the exact same thing, right? Well, visually yeah, but not according to Lua memory. Method two resulted in a memUsage of 117kb afterwards, a better result than just removing the main group. Granted 2kb isn’t much, but this was a simple example and I fear for what could happen in a large project.

Maybe I’m misunderstanding something fundamental here, but this looks like a gigantic problem for anyone using Director / Storyboard and just assuming that everything in your localGroup is going to be whisked away for you (which seems to very much be the general consensus around the forums).

Has anyone else encountered anything like this or would care to comment?

Brandon [import]uid: 136211 topic_id: 31652 reply_id: 331652[/import]

Just wanted to add on to this and say that removing each object from the display groups before removing the display groups seems to reduce memUsage even further.

local function removeAll()  
  
 display.remove(object1)  
 object1 = nil  
 display.remove(object2)  
 object2 = nil  
 display.remove(object3)  
 object3 = nil  
 display.remove(object4)  
 object4 = nil  
 display.remove(object5)  
 object5 = nil  
 display.remove(object6)  
 object6 = nil  
  
 display.remove(subGroup1)  
 subGroup1 = nil  
 display.remove(subGroup2)  
 subGroup2 = nil  
 display.remove(subGroup3)  
 subGroup3 = nil  
  
 display.remove(bigGroup)  
 bigGroup = nil  
end  
  
timer.performWithDelay(6000, removeAll, 1)  

Again, the difference is small (only .5 -1kb this time) but I think it’s still a valid concern. If this happens several times with several groups across several scenes… you’re talking hundreds of kilobytes before too long.

Or am I missing something? [import]uid: 136211 topic_id: 31652 reply_id: 126442[/import]

Hi Brandon,
How are you testing your memory readout? Do you just test it once, immediately after clearing your groups? If so, try using a repeating timer of about 1 second for each increment and test your memory each time. Watch the memory throughout the entire process. Try creating all of your groups, removing them, the creating them again and removing them again. Watch for a suspicious increase in memory usage each round: that’s a warning sign. Sometimes it can take a few more game cycles for Lua to really clean out everything… one instantaneous check is misleading.

Brent [import]uid: 9747 topic_id: 31652 reply_id: 126461[/import]

Hey Brent,

Yeah, I was testing the memory with a Runtime listener. Interesting that it takes Lua a few cycles to clean everything. Good to know. I’ll try setting up timers to recreates the group after they’re removed to see if anything interesting happens.

It just concerns me when these differences show up when they’re supposedly accomplishing the same thing. I’ve been racking my brain trying to eliminate these leaks. I’ve gone from gushing to a steady drip, but still!!

Thanks again,

Brandon [import]uid: 136211 topic_id: 31652 reply_id: 126462[/import]

Why don’t you try removing bigGroup first and then making bigGroup and all the rest of subGroups nill. Maybe you would get the same memory results. So far your first scenario only makes the bigGroup nill but not the subGroups [import]uid: 39846 topic_id: 31652 reply_id: 126502[/import]

Just wanted to add on to this and say that removing each object from the display groups before removing the display groups seems to reduce memUsage even further.

local function removeAll()  
  
 display.remove(object1)  
 object1 = nil  
 display.remove(object2)  
 object2 = nil  
 display.remove(object3)  
 object3 = nil  
 display.remove(object4)  
 object4 = nil  
 display.remove(object5)  
 object5 = nil  
 display.remove(object6)  
 object6 = nil  
  
 display.remove(subGroup1)  
 subGroup1 = nil  
 display.remove(subGroup2)  
 subGroup2 = nil  
 display.remove(subGroup3)  
 subGroup3 = nil  
  
 display.remove(bigGroup)  
 bigGroup = nil  
end  
  
timer.performWithDelay(6000, removeAll, 1)  

Again, the difference is small (only .5 -1kb this time) but I think it’s still a valid concern. If this happens several times with several groups across several scenes… you’re talking hundreds of kilobytes before too long.

Or am I missing something? [import]uid: 136211 topic_id: 31652 reply_id: 126442[/import]

Hi Brandon,
How are you testing your memory readout? Do you just test it once, immediately after clearing your groups? If so, try using a repeating timer of about 1 second for each increment and test your memory each time. Watch the memory throughout the entire process. Try creating all of your groups, removing them, the creating them again and removing them again. Watch for a suspicious increase in memory usage each round: that’s a warning sign. Sometimes it can take a few more game cycles for Lua to really clean out everything… one instantaneous check is misleading.

Brent [import]uid: 9747 topic_id: 31652 reply_id: 126461[/import]

Hey Brent,

Yeah, I was testing the memory with a Runtime listener. Interesting that it takes Lua a few cycles to clean everything. Good to know. I’ll try setting up timers to recreates the group after they’re removed to see if anything interesting happens.

It just concerns me when these differences show up when they’re supposedly accomplishing the same thing. I’ve been racking my brain trying to eliminate these leaks. I’ve gone from gushing to a steady drip, but still!!

Thanks again,

Brandon [import]uid: 136211 topic_id: 31652 reply_id: 126462[/import]

Why don’t you try removing bigGroup first and then making bigGroup and all the rest of subGroups nill. Maybe you would get the same memory results. So far your first scenario only makes the bigGroup nill but not the subGroups [import]uid: 39846 topic_id: 31652 reply_id: 126502[/import]