Which kinds of listeners require manual removal?

This question is related to this one with a bit more.

In my project, I have three kinds of listeners, and I’d like to know which ones require manual removal when I unload the module (in my case, when I unload a scene using Director Class). So far, I’ve been manually removing as many of them as possible right before the module is unloaded – but maybe I’ve been belaboring on adding lines of code when I really don’t need them:

  1. Runtime:addEventListener(“enterFrame”, myFunction)

  2. myObject:addEventListener(“touch”, myFunction)

  3. myObject:addEventListener(“collision”, myObject)

Now I have a feeling all I need to do is to manually remove runtime listeners like the type #1 above, but no need to remove listeners attached to objects like the types #2 and #3 (because they would be removed when the objects are removed). But then, I could be very wrong still.

I’d very much appreciate hearing your thoughts and/or pointers (and maybe a link or two to a post/article that answers my question – and if this has been discussed elsewhere, pardon my inability to locate them before posting my question here.)

Naomi [import]uid: 67217 topic_id: 17011 reply_id: 317011[/import]

Hello Naomi

I kind of recall a blog post from Jonathan Beebe which stated that you only need to worry (manual remove) about Runtime event listener. It was on his own blog not here. Sorry I do not have the link right at the moment.

Hope this help

Mo.

ps: personally I am just removing Runtime event… [import]uid: 49236 topic_id: 17011 reply_id: 63844[/import]

Hey Mo, thanks for responding!

Removing runtime event only sounds about right to me too. I’m going to comment out useless lines for now, and if I don’t hear or find out otherwise, I’ll permanently remove them. Whew, good to know that I probably don’t need to worry about another thing to manage when unloading a module.

Thanks again!

Naomi [import]uid: 67217 topic_id: 17011 reply_id: 63848[/import]

hey no problem!

Here the link where Jonathan Beebe talks about Runtime event listener removal:
http://blog.anscamobile.com/2011/08/corona-sdk-memory-leak-prevention-101/
Jon is the MAN in my book:)

Mo [import]uid: 49236 topic_id: 17011 reply_id: 63866[/import]

Hey, Mo, thanks for the link!

I read that blog a while back, but I guess it didn’t stick to my brain right – or, perhaps, along the way, my memory got mixed up and somehow, I decided I needed to remove all event listeners including the ones attached to the object. *sigh*

Thanks again!!

Naomi [import]uid: 67217 topic_id: 17011 reply_id: 63871[/import]

Well this all makes sense. RunTime listeners are not attached to objects, they are attached to the global program. The other listeners are typically attached to display objects that get removed when their parent group is removed, so their listeners should just go away. In fact I’ve tried to remove those listeners and its resulted in way bad problems.

So for me, I remove the RunTime ones, and let the object removal take care of the rest.
Dunno if that’s right or not, but its logical.
[import]uid: 19626 topic_id: 17011 reply_id: 63881[/import]

Thanks, Rob! Yeah, when a logical reason is given to a rule, it’s so much easier to remember the rule. This time, it’s definitely going to stick.

Cheers!
Naomi [import]uid: 67217 topic_id: 17011 reply_id: 63890[/import]

What method are you guys using to check for memory leaks? Print statements, instruments or something else?

When I was using print statements, I found that I had to delate all of these timers and then force a garbage collection to get consistent results. By that I mean, I would play the same level of my app over and over, always checking memory at the same point. I would get a range of values, but I could see that the results always fell within that range.

I’ve switched to using instruments to check for memory leaks, and just letting the Lua garbage collection run whenever it wants. If I do print the system memory, it’s all over the place and I can’t make any since out of it.

[import]uid: 67839 topic_id: 17011 reply_id: 63941[/import]

@elbowroomapps, I use print statements with collectgarbage(). When my game is ready to go live, I will remove the print statements but, unless I hear any advice against it, I intend to keep the collectgarbage() where they are now. I don’t see any harm in keeping it, but I could be wrong (and if so, I’d love to hear about it.)

Naomi [import]uid: 67217 topic_id: 17011 reply_id: 63945[/import]

You have to use both Instruments and good old fashion print statements.

While Instruments doesn’t give you a lot of info and it makes your app really slow while its checking and there is little to know information on using it, it does do a good job of pointing out when memory is growing. Vague locations like Audio Mixer or vsprintf only give you rough ideas (if its Audio Mixer, focus on your sound/music code), UIKit: probably not releasing objects, etc.)

Then for your own printing purposes. There are two blocks of memory that you need to measure: Lua memory and Texture Memory. While I don’t care for either of those terms, since it appears Texture memory is really used for any big blocks of allocated memory (audio, display objects etc. and not just “textures”. Lua memory is your variables, tables, strings, etc. I’m not sure which pool of memory display.newText comes from (I suspect Texture)

Lua memory can be found with one of two calls:

memory = gcinfo() or
memory = garbagecollect(“count”)

They are for a lack of better term, the same. I think there is a move to have us use gcinfo() instead. Both return the amount of non-texture memory in use and its measured in Kilobytes (1024 bytes).

Texture memory can be gotten like this:

texturemem = system.getInfo(“textureMemoryUsed”)

This value is returned in bytes and may be more useful scaled to MegaBytes which is likely how youu’re thinking about it. So:

texturemem = system.getInfo(“textureMemoryUsed”) / (1024 * 1024)

I found it helpful, in particular for games that have a beginning of a round, to measure there and see what’s different before you load up the new level.

When looking for leaks, you are looking for leaks that grow over time. For example, there is a leak in the Audio Mixer that happens at app start up, stands out big time in Instruments, but it only happens once. So don’t worry about tracking down that. But if your app is growing by a few megabytes every few minutes, you have to take care of that or your app won’t get approved or if it sneaks by Apple, then you’re going to get negative reviews when it starts crashing peoples phones.

Leaks in the kbyte range will probably get past Apple’s review process, but over time they will cause your app problems and they need to be taken care of.

Leaks in the 16 byte range, if you can find them, great, but I don’t spend a whole lot of time trying to hunt them down. It would take a very long time for a leak that small to be an issue. I shouldn’t say that. 16 byte leaks happening every 10 seconds is a problem. 16 byte leaks happening once a round or once every few minutes, not so much…
[import]uid: 19626 topic_id: 17011 reply_id: 64028[/import]

Wow, Rob, thanks for the detailed write up! I totally share your view/principle on the memory leak/management approach. About gcinfo(), now that I know what it does (and that it exists), I’ll look into using it. It sounds like a good function to know/use.

Thanks again!
Naomi

Edit: compared to collectgarbage(“count”), printing gcinfo() is better in that, it’s much easier to read when its value is printed on terminal. [import]uid: 67217 topic_id: 17011 reply_id: 64049[/import]