Posted on by
NOTE: This tutorial is outdated and has been replaced by the Performance and Optimization guide. Please refer to this guide for current details and usage examples.

Posted by . Thanks for reading...

31 Responses to “Tutorial: Memory Leak Prevention”

  1. Shane

    So if I have a display group and I use display.remove() to remove the whole group at one time, can I simply nil out the group declaration afterward, or need I nil out all individual display objects as well?

    Reply
    • Jonathan Beebe

      @Shane: If you have objects in a group, all you need to do is remove the group and the rest should be taken care of for you.

      @ Satheesh: Glad you found value in it!

      Reply
  2. Mo

    Another HIT! Thanks Jon.

    By the way am I right to think that I use director (1.2) that display objects are automatically cleaned up when when switching out of a screen (ie going back to a main menu screen from a game screen for instance). I am using the director clean() to delete runtime listeners, transistions, sounds.

    Is that the correct way of doing things with director?

    Thanks again, I am always excited to see another of this great series Of tutorials. Thank you for taking the time to doing this.

    Mo

    Reply
  3. Jonathan Beebe

    @Mo: Sounds like you’re doing everything right to me :-)

    Thanks for the comments everyone, they’re very encouraging! I’m glad you’re all getting some value out of these tutorials.

    Reply
  4. Janos

    One more thumbs up from me too, very helpful article Jon! Keep ‘em up, very appreciated!

    Reply
  5. Mario

    Jon, you rock. Thank you! Every time you come out with one of these I throw it in my bookmark folder for later review. The quality of these articles is fantastic!! Great subject matter, too!

    Thanks again!!

    -Mario

    Reply
  6. David Gross

    This variation only prints changes in the memory status:

    local prevTextMem = 0
    local prevMemCount = 0
    local monitorMem = function()
    collectgarbage()
    local memCount = collectgarbage(“count”)
    if (prevMemCount ~= memCount) then
    print( “MemUsage: ” .. memCount)
    prevMemCount = memCount
    end
    local textMem = system.getInfo( “textureMemoryUsed” ) / 1000000
    if (prevTextMem ~= textMem) then
    prevTextMem = textMem
    print( “TexMem: ” .. textMem )
    end
    end

    Runtime:addEventListener( “enterFrame”, monitorMem )

    Reply
  7. amanda

    This is very nice. My game has a lot of one-time transitions in it, i did not realize i needed to cancel them even after they were completed. I had this code in my main.lua and could not for the life of me figure out why I had such a bad memory leak!

    thanks a lot

    amanda

    Reply
  8. Tom

    @amanda,

    You don’t need to cancel transitions that have completed. They only need to be cancelled if they are still running when you need to switch screens (e.g., using Director).

    Reply
  9. Maarten

    Just saw this…. HANDY!

    Another tip: if you need globals for e.g. global state, put their declaration in a separate module that you require as first line in main.lua

    That way, keeping track of globals that might leak is so much easier.
    And, you force yourself to think twice before using globals.

    Reply
  10. GreenCastle

    I’m trying to track down a memory leak. I have noticed the amount of memory used jumps a little bit when the mouse is clicked – there are no event listeners running, so what is causing this? Sometimes it jumps a little and sometimes it does not.

    Reply
  11. Magnitus

    @Alexey – I tried your fps module. Works great. No mem leaks over here. Thanks!

    Reply
  12. Eugen Stolin

    I am trying to use the suggestion for cleaning timers and transitions. There is something I don’t understand. Does “timerStash.newTimer = timer.performWithDelay( …” really add a new item to the table? I’m maybe missing something but it doesn’t seem to work for me. When I do “table.insert” instead, it works as intended. What am I missing?

    Thanks in advance

    Reply
  13. Kyle

    @Eugen Stolin, @Fixdit

    The line timerStash.newTimer = timer.performWithDelay(.. does add a new item to the table, but it always does so under the key “newTimer”. It’s the equivalent of saying timerStash["newTimer"] = timer.performWithDelay(.. This means if you’re adding multiple timers with the line timerStash.newTimer = timer.performWithDelay(.., you’re constantly overwriting the previous timer under the key “newTimer”.

    “table.insert” is working for you because the table handles key creation for you, and you simply have to pass in the value. I think by default the keys will be an incremented integer (0, 1, 2 .. n), so you won’t have the overwriting problem mentioned above.

    I assume that using table.insert is fine if you don’t care about what key is generated. If you do care, then you’ll have to provide the key yourself, and keep them unique. So if you had multiple timers to add you would simply declare them like so:

    timerStash.characterTimer = timer.performWithDelay(..
    timerStash.sceneTimer = timer.performWithDelay(..

    and so on…

    The point is that different timers added to the table need to have different keys.

    “cancelAllTimers” will still work with these unique keys because it simply goes through all of the table’s key/value pairs, and cancels/nils everything.

    Reply
  14. Matthew

    If I have a lot of items in a group and each display object in the group is added to the physics engine as a body and then I remove the parent group that holds all the physics body display objects …. is there anything special there that I need to do ?

    Reply
  15. Mario Roberti

    To add timers or transitions to the stash incrementally as you go (as long as you don’t care about their names, like for one-offs or something) you can do:

    timerStash[#timerStash+1] = timer.performWithDelay(consoleSpeed, ScrollDialogBox, 0)

    and then call the CancelAllTimers function and it will work just peachy

    Reply
  16. Steve Woodward

    Ok, so is this right?

    I am using the director class…here is how I am managing memory…

    Every display object I create, I nil it out. I do this by incorporating a cleanup function for any transitions that take place…

    Every event listener I create, I also nil out, with the exception of Runtime, because that produced the same result, in my simulation, as dividing by zero.

    Every timer I create, I nil out. So I have a function that looks like this…

    –inside after win function or restart(pseudo)
    …if win == true then
    …other code here
    clean()
    …end

    –clean functions
    local function cleanDisplay()

    if object ~= nil then
    display.remove( object )
    object – nil
    end

    end

    local function cleanListeners()

    object._functionListeners = nil
    object._tableListeners = nil

    end

    local function cleanTimers()

    if timerStash.myTimer ~= nil then
    timer.cancel( timerStash.myTimer )
    end
    end

    function clean()

    cleanDisplay()
    cleanListeners()
    cleanTimers()

    end

    I am using this model right now, and it seems to work when I am monitoring memory. But it is a lot of code, and I have a minimum of display objects and listeners and timers. Can I get some feedback as to whether or not this is okay?

    Reply
  17. raman

    In database i update some data, it insert my data values in the table but if i relaunch it reset the table values i think it not storing in db if any knew the solution plz help me…………

    Reply
  18. mitchell hudson

    Most often you would have transitions that run and end in a scene. It’s only the currently running transitions that need to be canceled. If you’re adding every transition to a table you could easily end up with transition that have already competed in your table when the scene exits.

    Reply
  19. Ark

    Hi there! I have a question about this…

    Okay, we don’t need to cancel transitions that have completed… but we need “nil-out” them even if it had been completed ? or doesn’t matter?

    I mean… when a transition ends, value is nil automatically?

    Thanks!!

    Reply
  20. dellos

    i was pass your check memory code to corona sample code name Bridge. when i removed coconut. nothing change in texture memory. > ??? maybe someone explain why

    Reply
  21. WilerJr

    Very good! My game was getting up to 1.6 mb of memory used before I start using the function with collectgarbage() inside it. Now, the maximum it reaches is 600kb! :D

    Reply
  22. John

    I’m using the storyboard API when I leave and then return to my in game scene I notice that the memory usage has crept up. I’ve stripped the code right back to the bare minimum and the memory usage only creeps up a tiny amount but I have the understanding that It shouldn’t go up at all, i.e. if there were no memory leak.

    I remove the in game scene “storyboard.removeScene( previous_scene )” on the restart scene (which just returns to the in game scene again).

    I’ve tried removing all objects, setting them to nil and manually removing event listeners.

    I think I must be missing something but have no idea what. i ‘d like really like to get this sussed before developing the game further. I’m I correct in thinking that the memory usage should be the same every time the in game scene loads?

    Reply

Leave a Reply

  • (Will Not Be Published)