Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

[Guide] Finding/Solving Memory Leaks
Started by Danny May 21 2012 12:27 AM

* * * * * 2 votes
71 replies to this topic
[TOPIC CONTROLS]
Page 1 of 3 1 2 3
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

Danny

[GLOBAL: userInfoPane.html]
Danny
  • Corona Geek

  • 2,597 posts
  • Corona Staff

When you have memory leaks in your app/game generally there are several common things at fault. These are listed below, you should always adhere to these practices:

1) Always ensure to remove all runtime and object listeners before/during changing scenes. If you don't you will have both memory leaks and odd bugs.

EG


local function imageFunction(event)
    return true
end

local function runTimeFunction(event)
    return true
end
local myImage = display.newImage("myImage.png")
myImage:addEventListener("touch", imageFunction)
Runtime:addEventListener("enterFrame", runTimeFunction)

--Get rid of them
myImage:removeEventListener("touch", imageFunction)
Runtime:removeEventListener("enterFrame", runTimeFunction)

2) Always cancel timers when changing scenes and always as a rule create a variable to store your timer so you can cancel it.

EG:


--Create a forward reference for the timer (also known as "predeclaring"
local myTimer

local function testFunction()
    print("Hello")
end

--Create the timer
myTimer = timer.performWithDelay(1000, testFunction)

--get rid of the timer
if myTimer ~= nil then
    timer.cancel(myTimer)
end

myTimer = nil

3) When removing images be sure also to nil out the reference to the image, if you don't do this the lua garbage collector won't class it as garbage and it will remain in memory.

EG:

local myImage = display.newImage("myImage.png")

--Get rid of it
display.remove(myImage)
myImage = nil

4) When removing audio, ensure to follow the following steps:

Stop Audio > Dispose of audio > Nil audio handle and sound file reference.

EG:

local myAudioFile = audio.loadSound("mySound.mp3")
local myAudioHandle = audio.play(myAudioFile)

--Get rid of it
audio.stop(myAudioHandle)
audio.dispose(myAudioFIle)
myAudioHandle = nil
myAudioFile = nil

5) Always cancel transitions when changing scenes and always as a rule create a variable to store your transition so you can cancel it.
EG:

--Create a forward reference for the transition (also known as "predeclaring"
local myTransition

local myImage = display.newImage("myImage.png")
myImage.alpha = 0

--Create the transition
myTransition = transition.to(myImage, {alpha = 1})

--get rid of the transition
if myTransition ~= nil then
    transition.cancel(myTransition)
end

myTransition = nil

6) When creating functions to create objects (text, images etc) always make sure you return the object, if you don't then you have no way of clearing its memory

EG:

local function createBox()
    local box = display.newImage("box.png")
    
    return box
end

7) When changing text, change the text object directly, don't keep creating new text objects.

EG:


local function createHighScore()
    local highScore = display.newText("high score: 0000", 100, 100, native.systemFont, 24)
    
    return highscore
end

--Create the highscore text object
local highScore = createHighScore()

--Update the score
highscore.text = "high score: 0100"
But wait, I haven't been doing this and my game is leaking memory between scene changes

Don't worry, it's not too late. Here is one way you can work out what part of your code is causing the leak.

1) Code commenting. Start piece by piece commenting out sections of your code. Do this piece by piece though, don't rush ahead. Comment out say the function that spawns your enemies, start your game change scenes and monitor your memory usage, if it goes down (even by a small bit) you know that in the commented part of your code that you are leaking a bit of memory in there.

2) Comb through all your code files looking for things I mentioned above. It may take time but if you put the effort in you will see results.
How do i print my memory usage?

1) If you are using storyboard and have storyboard.isDebug set to true you can use the following command:

storyboard.printMemUsage()

I would recommend placing this in your enterscene function.

2) If you are using director, scene manager or are using something you created yourself... you can use the following function:

local function printMemUsage()   	
   	local memUsed = (collectGarbage("count")) / 1000
   	local texUsed = system.getInfo( "textureMemoryUsed" ) / 1000000
   	
   	print("\n---------MEMORY USAGE INFORMATION---------")
    print("System Memory Used:", string.format("%.03f", memUsed), "Mb")
	print("Texture Memory Used:", string.format("%.03f", texUsed), "Mb")
    print("------------------------------------------\n")
     
    return true
end

--Call it at the beginning of your new scene or the first line under your .new() function

printMemUsage()
Iv'e done all this but I am still leaking memory?

It is nearly impossible to write 100% bug/memory leak free code, it comes hand in hand with the profession. The following are safe regions of memory leaks and are nothing to worry about:

1kb > 8kb

If you are leaking more than that then I would suggest trying the things I have mentioned to get it lower.

You may find that your memory usage climbs for a while then drops off to it's original usage again, this is the expected behavior and how the lua garbage collector works, it's memory removal is not always instant, you need to bear that in mind.

Ok I've tried everything and I am still leaking more memory than you said should be ok

If you have exhausted every option, tried all my techniques, asked on the forums (etc) and are 100% sure your code shouldn't be leaking but it is, you have one last alternative. You can avail of our premium support service and one of our trained members of staff will work with you on your code. You can find more info on this here: http://www.anscamobile.com/corona/support/
uid: 84637 topic_id: 26628 reply_id: 326628


[TOPIC: post.html]
#2

Naomi

[GLOBAL: userInfoPane.html]
Naomi
  • Corona Geek

  • 2,303 posts
  • Enterprise

Thank you, Danny, for this post. It's super helpful.

By the way, you noted 1kb > 8kb is safe enough for memory leak. I'm wondering what you mean? Did you mean anywhere between 1kb and 8kb leakage should be tolerable?

Naomi
uid: 67217 topic_id: 26628 reply_id: 107910


[TOPIC: post.html]
#3

Danny

[GLOBAL: userInfoPane.html]
Danny
  • Corona Geek

  • 2,597 posts
  • Corona Staff

Yes anywhere from 1kb>8kb is nothing to be concerned about. If you go nuts like I did on my personal project, you can get it lower. Currently my own game leaks 1kb of memory and gains that 1kb back after a few scene changes. So basically I am leaking 1kb every 3>4 scene changes.
uid: 84637 topic_id: 26628 reply_id: 107915


[TOPIC: post.html]
#4

Axie Studios

[GLOBAL: userInfoPane.html]
Axie Studios
  • Enthusiast

  • 61 posts
  • Corona SDK

I've read all over the forum that when you remove the object it's EventLstener also get's removed so is this not the case?

local button = newImage("button.png")local function Do Something()--doing stuffendbutton:addEventListener("touch", DoSomething)button:removeSelf();button = nil;


In an example like this do I still need to remove it manually? Typing this next piece?

button:removeEventListener("touch", DoSomething)
uid: 123298 topic_id: 26628 reply_id: 109296


[TOPIC: post.html]
#5

soccermanandrei

[GLOBAL: userInfoPane.html]
soccermanandrei
  • Enthusiast

  • 46 posts
  • Corona SDK

Guys my multiscreen app doesn't seem to be leaking any memory between scenes (its under 2kb) but during gameplay the memory usage slowly crawls up to around 500 and only then gets collected by the garbage collector and this causes stutter on actual android devices. is this normal for lua memory to grow during gameplay? Note: I'm not spawning, adding event listeners or anything of that sort.

Even in this very simple code lua memory slowly rises...
http://codeviewer.org/view/code:27df
uid: 118482 topic_id: 26628 reply_id: 114882


[TOPIC: post.html]
#6

projects1

[GLOBAL: userInfoPane.html]
projects1
  • Enthusiast

  • 72 posts
  • Corona SDK

Hi Danny very useful post , helps new guys like me .

i have one doubt, if i use a display object to insert all my display items. is

disp_group:removeSelf()
disp_group=nil

enough or should i individually remove images like

display.remove(myImage)
myImage = nil

uid: 115284 topic_id: 26628 reply_id: 115010


[TOPIC: post.html]
#7

Cell Game Labs

[GLOBAL: userInfoPane.html]
Cell Game Labs
  • Enthusiast

  • 91 posts
  • Corona SDK

Hey great post but just a little typo

local memUsed = (collectGarbage("count")) / 1000


"collectGarbage" needs a lowercase g for Garbage

so will be:
local memUsed = (collectgarbage("count")) / 1000
uid: 26289 topic_id: 26628 reply_id: 115576

  • sieler2 likes this

[TOPIC: post.html]
#8

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

Great post Danny! Thanks you for that. I am wondering about one thing: using Director, do I really need to remove images (inserted into groups) since I was in the impression that Director would do that for me when changing scene? Am I wrong to think that?

Mo
uid: 100814 topic_id: 26628 reply_id: 117074


[TOPIC: post.html]
#9

Danny

[GLOBAL: userInfoPane.html]
Danny
  • Corona Geek

  • 2,597 posts
  • Corona Staff

@lairdGames, I haven't used director in over a year so I am unsure of it's current features. I'm sure if you posted that question in the director forums, you would get a proper answer however :)

uid: 84637 topic_id: 26628 reply_id: 117105


[TOPIC: post.html]
#10

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

Thanks Danny, I will. I am using the Modify version 1.2 (short 15 lines code one)

Mo.
uid: 100814 topic_id: 26628 reply_id: 117125


[TOPIC: post.html]
#11

nml

[GLOBAL: userInfoPane.html]
nml
  • Contributor

  • 202 posts
  • Corona SDK

thanks for this post, i just needed this!

if i manage my transitions from an external module and not the storyboard scene, should i also cancel them between scene changes??
uid: 105206 topic_id: 26628 reply_id: 118021


[TOPIC: post.html]
#12

Antheor

[GLOBAL: userInfoPane.html]
Antheor
  • Contributor

  • 345 posts
  • Corona SDK

About 6)

What if I do something like :
local mytable={}
local function createBox()
    mytable.box = display.newImage("box.png")
end
Is it ok ?
uid: 9328 topic_id: 26628 reply_id: 124924


[TOPIC: post.html]
#13

DPN Sweden

[GLOBAL: userInfoPane.html]
DPN Sweden
  • Observer

  • 20 posts
  • Corona SDK

I've read all over the forum that when you remove the object it's EventLstener also get's removed so is this not the case?
local button = newImage("button.png")
 
local function Do Something()
--doing stuff
end
 
button:addEventListener("touch", DoSomething)
 
button:removeSelf();
button = nil;
In an example like this do I still need to remove it manually? Typing this next piece?

button:removeEventListener("touch", DoSomething)


I also want to get an answer to this question!
uid: 199163 topic_id: 26628 reply_id: 134014


[TOPIC: post.html]
#14

Danny

[GLOBAL: userInfoPane.html]
Danny
  • Corona Geek

  • 2,597 posts
  • Corona Staff

@DPN Sweden,

When you remove an object any event listeners attached to it also get removed.
calling the following is enough

button:removeSelf() -- or display.remove( button )
button = nil
uid: 84637 topic_id: 26628 reply_id: 134018


[TOPIC: post.html]
#15

DPN Sweden

[GLOBAL: userInfoPane.html]
DPN Sweden
  • Observer

  • 20 posts
  • Corona SDK

Hi Danny
Okay thanks!

I am increasing my total memory use when I implement this, but the leakage remains constant. It would seem that Directors clean function takes care of my display objects like someone suspected. Time to look at media events instead.

uid: 199163 topic_id: 26628 reply_id: 134022


[TOPIC: post.html]
#16

ToeKnee

[GLOBAL: userInfoPane.html]
ToeKnee
  • Contributor

  • 232 posts
  • Corona SDK

Hi Noobie here,

So i am using Storyboard for my project.
I started testing memory by using the memusage function i found on the forums and it worked for me put it my main.lua file -
only thing it gives me the results every microsecond - thus spamming my terminal and as a result i can not see other print details which would help me progress through the test game procedure.

I want to try the storyboard.printMemUsage() - but can't get it to work - could someone provide an example of code format-
what goes in the Main.lua and what exactly you put on the scene.lua pages( is it need on all pages or just main?? - it's probably something simple but i'm missing it!

thanks
T
uid: 199068 topic_id: 26628 reply_id: 139684


[TOPIC: post.html]
#17

staytoooned

[GLOBAL: userInfoPane.html]
staytoooned
  • Contributor

  • 198 posts
  • Corona SDK

When using "storyboard.printMemUsage()" I am maintaining approximately the same system & texture memory on the enterscene where I placed this. Is this memory accumulating or does it clear every time the scene gets purged?

---------MEMORY USAGE INFORMATION---------
System Memory Used: 1.627 Mb
Texture Memory Used: 40.177 Mb
------------------------------------------

Also, is the above a safe amount. My app is crashing at the same point in this scene on the iPad 1.

Also, I am inserting all display objects into the group. Do I manually have to remove & nil them or do they automatically get removed and nilled when the scene is purged?

Thanks.
uid: 8780 topic_id: 26628 reply_id: 139979


[TOPIC: post.html]
#18

ToeKnee

[GLOBAL: userInfoPane.html]
ToeKnee
  • Contributor

  • 232 posts
  • Corona SDK

Hi staytoooned -
Thats a good question - so me +1
This thread is about memory leaks - and it states between 1 to 8 above -but thats a change in memory - what is a good target to keep Sys memory /Tex memory under - and are there device differences?

I got the storyboard.printMemUsage working (on each scene page) and combined it with the purge on scene change.

storyboard.purgeOnSceneChange = true

this produces what i think is the total memory used to create the scene, and because the scene is purged when changed believe this to be the total Mem Used by my app at that point in time.

What i did notice is with Universal building - as i changed the Simulator between IPad and iPhone the Texture memory certainly grew!

This i put down to the graphics (@4x) etc.. but it would be handy to know Memory targets that are safe to be under for each device if possible?
T

uid: 199068 topic_id: 26628 reply_id: 140006


[TOPIC: post.html]
#19

staytoooned

[GLOBAL: userInfoPane.html]
staytoooned
  • Contributor

  • 198 posts
  • Corona SDK

I still need to know if my display objects that I insert into the scene "group" automatically get purged (removed and nilled) when the scene gets purged with storyboard or do I manually have to removeSelf and nil them? In other words: Also, I am inserting all display objects into the group. Do I manually have to remove & nil them or do they automatically get removed and nilled when the scene is purged?

Please someone answer this question!

uid: 8780 topic_id: 26628 reply_id: 140963


[TOPIC: post.html]
#20

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,133 posts
  • Corona SDK

If you do a:

group:insert(somedisplayobject)

In your createScene(), willEnterScene() or enterscene() it will be purged and nil'ed when the scene is purged.

What is not removed is sound loaded in those scenes, timers, transitions that are not finished, any Runtime listeners (listeners on those display objects will be removed).

By default, storyboard scenes are only purged on low memory event warnings. You can turn on auto-purge, or purge the scene manually. In those cases memory should be cleaned up.

The iPad 1 only has 256M of memory and you at best can expect to get in the 40-80mb range on that device depending on what else it's doing.
uid: 199310 topic_id: 26628 reply_id: 140979


[TOPIC: post.html]
#21

Caleb P

[GLOBAL: userInfoPane.html]
Caleb P
  • Corona Geek

  • 1,424 posts
  • Corona SDK

Do you have to use variables for timers and transitions, or do they nil out on their own?
uid: 147322 topic_id: 26628 reply_id: 142073


[TOPIC: post.html]
#22

art.sherb82

[GLOBAL: userInfoPane.html]
art.sherb82
  • Observer

  • 1 posts
  • Corona SDK

Hi everyone.


Fighting memory leaks in my game I found one strange thing:
Corona itself allocates about 10..20 kb every second (exact numbers can differ depending on the platform)
10 kb in case of empty project (only main.lua)
20 kb, if config.lua is also present (with fps = 60)


Proof:
main.lua:

local t = {}
 
t.showMemoryUsage = function()
local textureMem = system.getInfo("textureMemoryUsed")
local mem = collectgarbage("count")
print("Texture mem: " .. (textureMem / 1000) .. " kb;\tmem: " .. mem  .. " kb")
end
 
t.startMemoryTracking = function(period, forceCollect)
t.memTrackTimer = timer.performWithDelay(period, function()
if (forceCollect) then
collectgarbage("collect")
end
t.showMemoryUsage()
end, -1)
end
 
collectgarbage("stop")
 
t.startMemoryTracking(1000, false)

 

 

You can change period from 5000 and play with 'forceCollect' to see that there are really 20 kb. Yes, they are cleaned up by gc, but that's not good anyway.

Can someone from Corona staff explain this?



[TOPIC: post.html]
#23

Jack01

[GLOBAL: userInfoPane.html]
Jack01
  • Enthusiast

  • 86 posts
  • Corona SDK

If you do a:

group:insert(somedisplayobject)

In your createScene(), willEnterScene() or enterscene() it will be purged and nil'ed when the scene is purged.

What is not removed is sound loaded in those scenes, timers, transitions that are not finished, any Runtime listeners (listeners on those display objects will be removed).

By default, storyboard scenes are only purged on low memory event warnings. You can turn on auto-purge, or purge the scene manually. In those cases memory should be cleaned up.
 

 

 

 

When you remove an object any event listeners attached to it also get removed.
calling the following is enough
 

button:removeSelf() -- or display.remove( button )
button = nil

 

Hi!

 

Does this mean :

 

1. when removing a group with buttons or objects with event listeners, all event listeners in the group get removed?

 

2. Does this also account for a group in a group in a group etc. ?

 

3. And if so, when using storyboard and the (multi layerered) objectsGroup is inserted in the storyboard group, nothing needs to be removed or nilled?

 

Thx



[TOPIC: post.html]
#24

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 25,133 posts
  • Corona SDK

1. Yes

2. Yes

3. Yes, if its attached to an object that has been put into the storyboard's scene.view (aka "group").  There are things that still have to be hand removed which includes:

 

  • Runtime listeners
  • Audio
  • Timers
  • Transitions
  • And stopping anything with an active call back  running (like doing a network.download and leaving the scene before the download finishes)

when we say Runtime listeners, we are talking about the ones where you do:

 

      Runtime:addEventListener("someevent", somefunction)

 

not:

 

   myButton:addEventListener("someevent", somefunction)

 

If myButton is in the scene.view, it will be taken care of.



[TOPIC: post.html]
#25

edulucats0

[GLOBAL: userInfoPane.html]
edulucats0
  • Observer

  • 13 posts
  • Corona SDK

I'm having a HUUUGE memory leak ... I'm cleaning every local variable in my code and I can free about 20 ~ 30 of memory! And its using about 600 bytes of memory in my scene 

 

Using the profiller tool in mode 4 it shows me that the variables that are using most of memory are those of the array of the spritesheet, the ones generated by the function newSpriteSheetFromData(). I'm removing the spriteSheet with dispose() , but even so the memory isn't cleaned ... there is anyway of cleaning this array?

 

Another question ... i'm using "module (..., package.seeall)" to create classes and to assess variables in this classes i'm using set and get methods. The profiller tells me that some of this gets and setters are consuming a considerable amount of memory! There's any way to clean the memory associated with this functions? 

 

Thanks for the help! 




[topic_controls]
Page 1 of 3 1 2 3
 
[/topic_controls]