Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Garbage Collector

Discussion in 'Scripting' started by LightStriker, Jul 16, 2014.

  1. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Working on a fast pace game where performance is key. We have great CPU time - under 2 ms on PC - and generate very little garbage, which means the collector pass once every 1-2 minutes.

    However, from the profiler, we see that the GC takes 7 to 9 ms to perform its task when it decides to do it. On mobile, that could mean 24 to 40 ms, which would kill our framerate once in a while!

    Now, I have no definitive proof that it occurs on mobile, but the number in Unity profiler are not fun to look at.

    1) In the .NET Framework, the GC is multithreaded by default... is it in Unity?

    2) Is there a way to reduce that GC spike? Calling it every second is not an option, as it's just having a 6-7 ms spike every second instead of 7-9 ms every minute.

    3) Shouldn't the GC be fast? So why is it so damn slow in Unity?

    4) Is it slow because it has many objects to parse? We don't have that many object, but is there a way to make it ignore some we know we will never destroy?
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    I have read heaps of complaining about the slowness of Unity's garbage collection. (Well, I've read it like 2 or 3 times.) Unity uses a pretty old version of Mono, and that version has notoriously slow GC. FWIW, I also recall hearing that Unity is working on this, though it might not come to fruition until IL2CPP is finished (perhaps sometime in the 5.x cycle). There's some discussion about it here, along with some memory management tips. (I'm actually reading it right now, as I believe I have some GC issues of my own.)

    Speaking of memory management tips, I'm sure you've seen this page, which might help a bit in reducing the frequency of GC.

    You can manually call system.GC.Collect() at opportune moments. If the player opens a menu, during any level transition, if there's a moment (even one a fraction of a second long) where you know there will be no action, anything along those lines, you can take advantage of it and call the collector.
     
  3. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Sadly, it's an endless fast pace runner, there is no downtime to perform manual collect.
     
  4. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I think the only way to fix it, is to have no garbage at all.

    what is generating your garbage?
     
  5. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Well, an endless runner requires to spawn road and gameplay. We have pooled everything that can be pooled, but it still leaves us with a few bytes of garbage every few frames. Sorry, I'm at home, so I don't have an exact list.
     
  6. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    Yep Im working on an endless-ish runner.. however mine is dead basic. No GC so far. What havnt you been able to pool out of curiosity?
     
  7. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    We have dozen of different track models, and each model got a collection of potential "pattern" of gameplay that can spawn on it. We pre-spawn 6 tracks module ahead of the player... So precaching all our stuff would be insane.
     
  8. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    I use the PoolManager asset by Path-o-logical Games which is fantastic for pooling things: http://poolmanager.path-o-logical.com/

    Since you have patterns perhaps it would be worth having a sort of sub-pooling system whereby you pool the pattern, and then inside OnEnable() of the pattern you proceed to rebuild the pattern from pooled parts.

    This way you would be able to reuse parts between all patterns which share them.
     
  9. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    Already done... Like I said, everything we could realistically pool is already pooled.
     
  10. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    In one of his QuakeCon talks John Carmack posited running the GC every frame in an effort to have a more even, consistent experience. He figured a known overhead every frame was better than an unknown dip in performance at uneven intervals.

    Made me wonder if anyone has actually ever tried that. Given that it isn't a "standard practice" I would imagine someone has with not so great results.
     
  11. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    I did, and it's no good. The GC have to read all the heap pointer to see which variable is dead, and from what I see, that appears to be the slowest part of its job. Calling the GC every frame or every few frames still eat 6-7 ms of CPU, which on mobile means it would be impossible to have a steady 30 FPS.
     
  12. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Could you explain why it is impossible to pool everything?
     
  13. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    When you have 50 tracks type, with each having 10-12 possible pattern... Would you really pre-cache everything, even more considering the same track or pattern can happen twice?
     
  14. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    I have certainly no idea how the game works. Would it be possible to make a selection at the beginning and then just use those ones?