OK, I'm doing some work on making sure that my app isn't leaking memory and I'm finding it a real head-scratcher. For the purposes of explanation I have two main parts - the front-end and the actual game. I'm finding that the front-end is leaking around 100k each time it unloads. It was much more until I decided to add by own object cleanup - the front-end has a large number of sprites in the background which are added to a table and added to the parent sprite (FrontEnd) as they change continually and wanted an easy way to reference them - so I'm removing them from the parent and then nil'ing the table they're held in. This, I think, is part of the problem and a disconnect in my thinking about Lua memory management - I guess when using Objective-C I'm used to having to control it all myself but, not having some release method built in in Lua, you can't do that easily so I'm kind of stumbling around a bit. Would event listeners cause an instance's memory not to be freed up? I'm calling Timer.stopAll() as I'm aware that running timers could stop collection. Following
@atilim's code on the forum I'm calling collectgarbage() 4 times before doing a collectgarbage("count"). But does anybody have any tips here on what to look out for that would cause things not to get released.
Secondly, I'm using a single packed texture for all the artwork. The front-end reports no change to the texture memory usage when it unloads. However, the game itself is reporting a 1mb increase each time it unloads. I am using some TTF text but I'm also using this on the front-end as well. Now I'm trying to think why this could be. I'm using a sprite cache for a lot of images, grabbing the texture regions and keeping them in a global for performance reasons (I've found this quicker than trying to grab texture regions as needed) but there are still areas where they are being grabbed as needed. Does that act of grabbing a texture region actually make an increase in texture memory usage? Is that correct? It's not what I'd expect.
So anyway I'm a bit confused and need to get my thinking straight. I haven't tried the XCode tools yet, I'm trying to see what kind of memory work I can do in Gideros itself first.
Sorry it's a bit of a long, wordy, post. Just want to get my head around Lua's memory management.
Comments
That is why you get the same texture memory when you do unloads. (i assume you didn't do collectgarbage() after nilling it), since it works fine for me.
collectgarbage() can be so dangerous, for example, if you're using TNT particle engine, and assign emitter to local variable, and in the middle of the animation you do collectgarbage(), sometime the animation just stopped right away and event.complete won't be called.
But it is okay, if the emitter is global variable, i think.
The same thing applied on Timer, and MovieClip objects.
That is also why i always applied Event.ENTER_FRAME only on stage, and not on my local objects. Because if i can remember, collectgarbage() will be called if memory warning is received. Just to make sure.
Second reason, is that it is time consuming, so i won't call it each time i remove an object.
Haven't tried XCode tools also.
That is weird, i tried it again now, and it works just fine.
No memory leak, goes up and down just fine...
Well, at least i can say that it is actually work just fine in Gideros.
I always tried to manage memory usage, so i know for sure about it.
Well, Gideros... works normally just like lua...
Can't say much about how it works also. I just tried to maintain things normally. Global as strong, and local as weak, perhaps?
I also do grab some of the texture on the first load, and do load others on the middle of the process, just like you did.
But all of my objects, instead of audio, texture, and main layers, is assigned on local.
Whilst they are local maybe it's because they, in turn, are referencing a global, i.e. the texture region from the sprite cache. In which case this seems a little odd, as surely it's just storing a reference to the global - would that really stop a local (self.) variable from releasing its contents - if its contents were referencing something from a global?
You see, this is why I'm a little confused about Lua's memory management.
I don't even release texture from a sprite. I just remove a sprite from it's parent.
i also do referencing a global things, but to local variable, like:
local something = something
It is explained somewhere i think.
http://www.giderosmobile.com/forum/discussion/comment/9441#Comment_9441
Likes: moopf
On other lua engine, C*... If we call object:removeSelf() the object was cleared completely, and i don't need to call collectgarbage() at all.
Maybe it would be possible to adopt something similar. How about creating a global texture manager class, where you request a texture and it get's loaded and cached if it's requested again. I don't completely know/understand your way, but this way you could manage texture loading/unloading/caching through class properties, by some keys as texture names, etc
Did you do something like local newTexture = globalTexture ?
But it looks like I'm getting hung up on something that is only being reported from the desktop player in terms of overall Lua memory usage. At least, I think so anyway...
I don't think it is much difference... Dunno, never tried to load the texture separately like that.
Some time ago, Atilim described a "secret" function that allows you to tell when a particular variable is collected.
Likes: moopf, twisttap, Platypus
https://github.com/gideros/gideros
https://www.youtube.com/c/JohnBlackburn1975
Likes: ar2rsawseen
1. The code posted by @john26 is incredibly useful to track where a leak is happening. Use it on the higher up objects first to see if they're being collected correctly, gradually working your way down through the child classes until you find one that isn't being collected.
2. Even using that, and even if you call collectgarbage() multiple times in a row, expect Lua to be lazy on actually collecting an object that's garbage. Don't expect to see the messages from the code from point 1 straight away, sometimes Lua likes to take its time.
3. Don't expect XCode's Instruments to report leaks. It continually told me I had none when I actually did and lots of them. I don't know why this is, I can only presume that Lua obfusticates leaks from the XCode instruments. This is only based on what I've seen today, your mileage may vary.
4. collectgarbage("count") and application:getTextureMemoryUsage() are useful. They're not always 100% accurate but they can definitely be used to track a trend. If they're both going up the longer your app is running then something is up. Just don't over-analyse the figures too much.
5. If you're used to being in control of garbage collection, for instance if you're used to Objective-C, then prepare to give up a bit of control and let Lua do its thing. It does do it, just not as immediately as you might want it to.
Anyway, the feedback on this thread has been really useful so thank you all that participated and I hope the cliff notes above help others (even if just a little bit)
Likes: Platypus
Well, for me, i hope that Gideros can remove an object completely from the Application, not just remove it from stage, since watching memory rising up in the game scare me.