Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Taking out the trash...

edited December 2013 in Questions Posts: 140

I've been poking around and I can't seem to find anything on garbage collection and memory management. Questions:

  1. Can it be forced? I saw there used to be a collectGarbage(), but I am unable to find it in the reference. I will be using a number of nonce images created and disposed of on the fly and I'd like to force gc on very large sets. I'm assuming setting an object to nil will mark it for collection.

  2. In a stand-alone app, when the app is sent to the background, what sort of strategies are used to relinquish memory? Is garbage collected? is any part of the runtime unloaded? or, do Codea apps run in a 64K memory space? :D

Comments

  • Posts: 2,042

    There is a collectgarbage function (might by garbagecollect or collectgarbage, I'm not sure) it just isn't documented as far as I know,

  • edited December 2013 Posts: 140

    Hrm. Maybe I should have tried that then... brb

    Back! Apparently, it's collectgarbage(). I habitually CamelCase everything after using Java so long.

    Thanks!

  • edited December 2013 Posts: 502

    lua handles garbage collection automatically. but in some cases you want to take more control over it and force it manually at need. in this case call collectgarbage()

    sometimes you need to repeat the garbage collection cycle more than once, to achieve the desired effect. that's why people like to call:

    collectgarbage()

    collectgarbage()

    collectgarbage()

    ...when forcing lua's GC.

    example:

    if scene then --scene variable not empty
        scene = nil --empty scene variable
    
        collectgarbage() --force lua's GC cycle 3x
        collectgarbage()
        collectgarbage()
    end
    
  • Posts: 2,820

    Codea's documentation of Lua's functions is nowhere near completely. I might spend some time committing parts to the Wiki docs sometime. Yo might also try my Objective C library for better automatic garbage collection (fixed most crashes in my app): http://twolivesleft.com/Codea/Talk/discussion/4221/objective-c-libraries:-testflight-gamecenter-location-twitter-facebook-camera-roll-sharing-more#Item_9

  • IgnatzIgnatz Mod
    Posts: 5,396

    I am no expert on garbage collection, but it makes a huge difference in some cases. It seems to run about every 60 seconds in Codea.

    It has a very important effect with physics objects, where, if you delete references to them, they stay "alive" until the next collection, like zombies, that may interfere with other physics objects. You need to explicitly destroy physics objects before deleting their reference variables, so it is a two step process. This is documented in the physics:destroy function.

  • Posts: 18

    I have been writing a large program with lots of states and lots of stuff on the screen. There is a state I can get my game in where it will consistently crash Codea if I leave it alone for about a min. I cant help but wonder if this is when the garbage collection is happening.

    I have been poking around here and thought that maybe collectgarbage() sprinkled about might help me but it sounds like it mostly helps physics which I have none.

    Is there other best practices for when to use collectgarbage() ?

    thanks

  • edited December 2013 Posts: 140

    Thanks, all. I think just forcing it between scene changes will be enough. Running a scene itself won't generate trash, just destroying it.

    Anything on my question #2? Do I need to worry about releasing memory at all if my app gets sent to the background? Or, do I just need to check if data structures need to be (re)built on method entry?

  • edited December 2013 Posts: 398

    @syntonica - as for point 2. I guess there's no easy way for your Lua code to know directly that once its compiled and running as an app that its been suspended.

    You'll probably need to hook in some Objective-C (via Xcode) that communicates the current App State to your code using the app object delegate when it transitions into the 'background' state before its suspended . You should be able garbage collect at this point before it goes to sleep.

    Indeed, once suspended and if any foreground apps need additional memory resources (should it be running low) the system will purge suspended apps without warning.

  • Thanks, Andy. Looks like I will have to save the running state regularly. I have no desire to poke around in Cocoa--last time I tried it, it was like a straightjacket.

  • @syntonica and @Dwight - there's also some compelling arguments for tuning the garbage collector to be more aggressive regarding the frequency of how often it executes, rather than simply splattering your code with individual GC calls.

    The collectgarbage command has 2 optional args for tuning the performance of how often it goes into garbage collecting mode (setpause and setstepmul) - the Lua docs (at lua.org) should give some more technical insight on how this works in practice.

    It's also worth mentioning that efficient use of local variables should reduce the need for extensive calls to GC as they use the stack for automatically releasing memory when no longer used (rather than via the main garbage collecting cycle).

    Use of locals also has the additional advantage of speeding your code up as well. :-)

  • @andymac3d. I haven't looked under the hood at Lua yet to see how the VM has been implemented. When you say stack, I'm assuming the machine stack and not a virtual one?

    Does Lua always use stack frames or will it optimize some locals to registers? Or, am I talking JIT compiling at this point?

    Agreed that more aggressive gc can work if the code is regularly littering old objects. The shorter pauses should not be noticeable at all if a frame or two is dropped.

  • @syntonica - to paraphrase the Lua docs, locals are stored in the VM registers and referenced by index. Globals on the other hand are stored in a table and are accessed using a hash lookup - which is much slower.

  • Jmv38Jmv38 Mod
    Posts: 3,295

    @syntonica the garbagecollector is a must when you use lots of graphics. Google it to know what are the functions and force it after you set big objects to nil.

  • edited December 2013 Posts: 140

    @andymac3d. I just slogged through 100 pages learning Lua and now you want me to read more? :((

    @Jmv38. That's my plan. :)

  • Posts: 152

    @syntonica

    I had a similar problem in my game, it didn't crash but the memory seemed high. I use this to track the memory and FPS so I can always see the 'state':

    -- Globals
    local FPS = 60
    local elapsedTime, memory = 0, 0
    
    -- put below in setup()
        -- Initialise our metric counter
        elapsedtime = ElapsedTime
    
    -- Put in Main draw func
    if (ElapsedTime - elapsedTime > 1) then
            memory = collectgarbage("count") / 1024
            elapsedTime = ElapsedTime
        end
    
        pushMatrix()
        resetMatrix()
        pushStyle()
        fontSize(20)
        FPS = FPS * 0.9 + 0.1 / DeltaTime
        text(string.format("%.0fFPS %.1fMB", FPS, memory), WIDTH - 80, 64)
        popStyle()
        popMatrix()
    

    This webpage also helped me quite a lot:

    http://bitsquid.blogspot.co.uk/2011/08/fixing-memory-issues-in-lua.html

    I also had to trawl the code a LOT to find dangling references to objects which held other objects which held other objects etc.

    Lua's default garbage collection algorithm is not so well suited for high frame rate games (from what I have read), so a judicious use of collectgarbage(), especially after large objects have been dereferenced is probably necessary. I actually make a single collectgarbage() call every 10 seconds to give the VM a 'nudge' in the right direction...

    brookesi

  • @brookesi - nice link and some good 'practical' advice!

    I'm a big advocate of the 'garbage collect small and often' school of thought for games - I guess this is pretty much the optimum solution when a game is running where large numbers of things are being created and destroyed, and then do a big forced garbage collect at a natural pause in the game, such as the end of a level.

  • Posts: 18

    Thanks for all the replies.

    I tried the code @brookesi posted. It's fun and interesting.

    It doesnt stop my game from crashing. Even though it calls collectgarbage often. Is there documentation on collectgarbage somewhere? What dies it output? Does the output change based on the string you feed it?

    Thanks

  • IgnatzIgnatz Mod
    Posts: 5,396

    just google "lua collectgarbage", there's no docs in Codea on it

  • Posts: 18

    @Ignatz thanks. Don't know why I assumed it was a Codea thing.

  • Posts: 140

    Just a quick update. Since I am now running at 60fps on all screens now, I ended up putting collectgarbage() in the touch ended loop! I may drop a frame here and there, but I no longer have collectgarbages littered all over my code. If the player is sliding something around, it makes a great spot to tidy up when they finish.

Sign In or Register to comment.