Skip to main content
Participant
March 12, 2016

[FREE Unity Plugin] Memory Efficient Coroutines

A lot of VR environments require movement, and a lot of movement is done in Unity using coroutines. However, many people don't know that coroutines allocate about .1kb of memory on the heap per running coroutine per frame. The garbage collector has to come clean that up later which causes random framerate spikes. If you use a bunch of coroutines then these spikes can end up happening more than once per minute. We all know that framerate is a very important issue in VR environments.

That's why I've released Memory Efficient Coroutines for free on the asset store. It produces zero per-frame allocations and can easily replace Unity's coroutines in your project. I hope that everyone who sees this will try it, and if you do please leave a review or at least a star rating. Thank you.
    This topic has been closed for replies.

    9 replies

    Up and Coming
    March 16, 2016
    Hi,

    Since no-one has said thank you, I'll just take a moment to say "Thank you!". It's this kind of work that is a key contributor to everyone producing better and more consistent Unity experiences.

    Just out of interest, I use extended co-routines (by the equally amazing Twisted Oak Studios) in my builds to handle exceptions and return parameters. Would your library integrate with that?

    https://www.youtube.com/watch?v=ciDD6Wl-Evk
    http://twistedoakstudios.com/blog/Post83_coroutines-more-than-you-want-to-know

    Peter
    Check out my Unity VR development blog: http://talesfromtherift.com @peterept
    Inspiring
    March 16, 2016
    Nice work.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
    Inspiring
    March 16, 2016
    I'm using a fair number of coroutines currently, so this sounds great! I'll check it when I have the chance.
    Scorched Battalion - VR Jam edition available for Gear VR and DK2 (Win/Mac/Linux) Jungle Juice Sven Co-op
    AblazeAuthor
    Participant
    March 20, 2016
    "peterept" wrote:
    Hi,

    Since no-one has said thank you, I'll just take a moment to say "Thank you!". It's this kind of work that is a key contributor to everyone producing better and more consistent Unity experiences.

    Just out of interest, I use extended co-routines (by the equally amazing Twisted Oak Studios) in my builds to handle exceptions and return parameters. Would your library integrate with that?

    https://www.youtube.com/watch?v=ciDD6Wl-Evk
    http://twistedoakstudios.com/blog/Post83_coroutines-more-than-you-want-to-know

    Peter

    Thanks Peter :)

    The key thing that makes MEC run without per-frame alloc is that it doesn't use a generic object in the return value like Unity's coroutines do. It's the type casting of this yield return <object> that causes the heap allocation. However, that does make it so you can't hook additional types into the return value.

    As for exceptions, the default behavior is to output them to the console. However, the file isn't compiled to a dll or anything, so you can find the three try-catch blocks in the script and change them so they point to your custom error handler.

    So, no on the returning values and yes on the custom exception handling.
    Inspiring
    March 21, 2016
    When following the instructions in the PDF, changing "yield return null" to "yield return 0f" etc. and attempting to use:
    private IEnumerator<float> ListenForAudioStop(AudioSource src)

    I receive the errors:
    error CS0308: The non-generic type `System.Collections.IEnumerator' cannot be used with the type arguments
    error CS1624: The body of `...ListenForAudioStop(AudioSource)' cannot be an iterator block because `IEnumerator<float>' is not an iterator interface type
    Scorched Battalion - VR Jam edition available for Gear VR and DK2 (Win/Mac/Linux) Jungle Juice Sven Co-op
    AblazeAuthor
    Participant
    March 21, 2016
    I may not have updated that PDF recently. There's more up-to-date documentation on my website, here.

    In order to get rid of that error you need
    using System.Collections.Generic;
    Inspiring
    March 21, 2016
    Thanks! That fixed it. Unimportant, but the documentation says to use Timing.StartCoroutine(), while the method name is Timing.StartUpdateCoroutine().

    By the way, the methods don't return a Coroutine object. I'm currently saving my coroutine reference and aborting it with StopCoroutine() under some circumstances. Is there any way to do something like that using MEC?

    Interestingly, the profiler will only show GC Alloc for Coroutines with Deep Profile *disabled*, for some reason. Strange.

    (On a separate but related subject, even in a completely empty project the profiler shows Total GC Alloc rising gradually from 7.6MB to 10.4MB and getting garbage collected every couple of seconds. The only case of GC Alloc listed in the profiler is 32B per frame for GameView.GetMainGameViewRenderRect(), but that doesn't add up so there must be something else not shown.)
    Scorched Battalion - VR Jam edition available for Gear VR and DK2 (Win/Mac/Linux) Jungle Juice Sven Co-op
    Up and Coming
    March 29, 2016
    Thanks! Is it always more efficient than Unity's or just in certain cases?
    AblazeAuthor
    Participant
    March 30, 2016
    @SvenViking There is a KillCoroutine function. I just submitted an update that will allow you to either kill a coroutine by passing in the type (in which case it will kill the first found instance of that named function) or you can pass in the coroutine's instance you want to kill.

    That is really interesting that deep profiler doesn't show the GC alloc. You could be seeing all that untracked alloc because the profiler itself creates a lot of overhead (but obviously only when it's running.)

    @vidonme It's always more memory efficient. They should be more processor efficient as well, but I haven't had a chance to profile them side by side yet.