- Home /
force and delay Garbage Collection
Is there a way to force or delay Garbage Collection? My app has natural pause points were I would prefer garbage collection to happen if it's going to vs in the middle of my animation.
Answer by duck · Nov 17, 2009 at 06:08 PM
You can call GC.Collect() to force the Mono garbage collector to kick-in, but it's worth being aware that this only works on Mono objects and not Unity objects.
Unity has its own method of dealing with destroyed Unity objects, but perhaps the main thing you should be looking at is how to avoid having lots of destroyed objects in the first place, if it is significantly affecting your app's performance.
If you're targeting iPhone, you'll need to become famililar with common techniques such as re-using a pool of objects rather than creating and destroying repeatedly.
More information about what exactly your app is doing might help to pinpoint the problem.
Answer by Michael La Voie · Nov 17, 2009 at 07:09 PM
I can't comment on the subject of Unity's garbage collection (though it would be great if a Unity developer could weigh in).
As for calling
GC.Collect()
It will call the mono garbage collector, but you need to know how it works before calling it because 99% of the time it is a horrible idea to call the garbage collector manually and it will actually slow down the process.
The short of it is that the garbage collector has three levels of memory: 1) short term, 2) middle term and 3) long term. A simplified model of what happens is that all data starts out in short term. When it fills up, the GC deletes any unused memory and anything currently in use gets "promoted" to level 2 (middle term). It will keep clearing out level 1 every time it fills up.
If, while promoting something to level 2 it finds that level 2 filled up, it will do the same thing there, promoting everything still alive in level 2 to level 3.
Problems arise if the GC is called too often, because it can lead to short lived variables making it to level 3. If you haven't guessed it, the GC is almost never called on level 3 unless all three levels are full even after clearing level 1 and 2.
If you call GC.Collect() yourself, you risk promoting short lived variables into level 3 (long term memory) and effectively preventing them from ever being released.
These two articles discuss it and when its ok to call GC.Collect(). (It is ok to do sometimes, maybe yours is one of those times...)
StackOverflow question - What's so wrong about calling GC.Collect()?
That would make sense if unity was using a generational gc. Sad thing its not ...
Indeed, you are right, Unity's garbage collector is "non-generational"
Crucially, Unity’s garbage collection – which uses the Boehm GC algorithm – is non-generational and non-compacting. “Non-generational” means that the GC must sweep through the entire heap when perfor$$anonymous$$g a collection pass, and its performance therefore degrades as the heap expands. “Non-compacting” means that objects in memory are not relocated in order to close gaps between objects.
Answer by synapsemassage · Jun 27, 2011 at 08:13 AM
Here you will find useful info about garbage collector: http://unity3d.com/support/documentation/Manual/iphone-Optimizing-Scripts.html
Answer by Oliver-Bogdan · Aug 08, 2017 at 10:50 AM
It is never a good idea to call the Garbage Collector manually. Instead you can focus on producing less garbage to start with, the links at the end will help you with achieving this. If you find it absolutely necessary to do it manually and you know what you are doing, you can force it by calling GC.Collect()
and in Unity you should/can also call the following Resources.UnloadUnusedAssets()
As stated in the documentation, Unity's GC is non-generational and so there is no persistent penalty associated with calling it frequently (no promoting to higher generations)
Crucially, Unity’s garbage collection – which uses the Boehm GC algorithm – is non-generational and non-compacting. “Non-generational” means that the GC must sweep through the entire heap when performing a collection pass, and its performance therefore degrades as the heap expands. “Non-compacting” means that objects in memory are not relocated in order to close gaps between objects.
You can find more info on the subject here:
Answer by cgarossi · Aug 08, 2017 at 01:25 PM
Unity is all managed code, so GC should happen automatically. Calling GC manually is a sign that something is structurally wrong with your code.
Some basics:
Keep variables in scope. If you have variables that you only need for a limited time, declare them as close to their usage as possible. Don't declare them globally where they can be referenced. The GC will not collect objects that are still being referred to even if you are not using them anymore.
Don't construct unnecessarily . Create factories for objects which control their distribution. For example, if you have a list of resources, create a factory that instantiates these resources for you and keeps track of them. If you don't require a new copy, just grab it from a resource manager instead (singleton factory). If objects are no longer required in the scene, keep them by for later use in your manager. Destroy them when you really don't need them anymore and the GC will do it's work.
Use Static classes for data objects. Static classes occupy a single memory space and do not need to be constructed. They can be used to contain common functions that you regularly refer to or you can use them to store globally accessible data, such as scores or other stats. Since they do not require construction they also don't require destruction and so the GC will ignore these and will only tidy them up when the application exits.
Hope this helps.
Actually "Unity" is almost all native code, not managed code as it's written in C++. It's all of your scripts which are managed. $$anonymous$$ost Unity classes you interact with are just managed wrapper classes (types like GameObject, Transform, Rigidbody, Collider, ... ).
Basically all "Unity" classes that are derived from UnityEngine,Object are actually native classes. They are not garbage collected once all managed references are gone as they are tracked objects on the native side. It's true that the managed wrapper is garbage collected as usual but only when the native part has been destroyed and all references are gone.
Yes even if the core Unity elements are native code, they are wrapped in a safe managed object that abstracts it's construction/destruction via the regular .NET methods. So you could say that it's as good as managed code, since the average user will never delve much deeper than the friendly managed layer.