Search Issue Tracker
Postponed means that the issue was either a feature request or something that requires major refactoring on our side. Since that makes the issue not actionable in the close future we choose to close it as Postponed and add it on our internal roadmaps and technical debt pages instead.
Postponed
Votes
69
Found in
4.3.4f1
Issue ID
590565
Regression
Yes
Excessive garbage generated when accessing a non existent component
The project consists of two scenes:
1. GarbageTestCaseScene - it has a GameObject with a component/behaviour calling GetComponent() multiple times per update while the asked component is missing.
2. NoGarbageTestCaseScene - it has the same component/behaviour but it asks for a component that exists on that GameObject.
To reproduce:
1. Open the attached project
2. Run the GarbageTestCaseScene
3. Open the Profiler
4. In "CPU Usage" tab uncheck everything except "Garbage Collector"
5. See that a lot of garbage is generated every frame
6. Now run the NoGarbageTestScene
7. Look at the Profiler
8. See that no garbage is generated
The only difference between the scenes is that the first one is accessing a component that is not attached to a game object.
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- GPU utilization increases by 20% on Meta Quest headsets when Render Graph is enabled on 6000.0.16f1 and higher
- Value on Slider (Int) control in UI Builder displays as default when saving UI Document
- Color mismatch in UI Builders Library panel when the Editors theme is set to Light Mode
- [Android ] "AndroidJNI.ToBooleanArray" returns a random non-zero value instead of "IntPtr.Zero" when the method argument is null
- Non-HDR color picker opens when selecting material color with HDR enabled
shubhamswaraj2021
Aug 18, 2020 16:47
good one <a href="https://www.lyricsauto.com">lyricsauto</a>
Paul_Bronowski
Dec 26, 2016 03:13
This is not good. Think about how many people are writing Editor code are calling GetComponent() and then checking for null. For example: Fabric Audio Editor code is causing a huge perf hitch for us because of this problem. Our designers need to do audio timing adjustments in the Editor, not at runtime (that's would be an unacceptable workflow). Editor performance matters, folks. Bad editor performance => wasted development time and a lot of money.
If these old posts have anything to do with the problem...
http//:answers.unity3d.com/…/-garbage-when-the-comp.html
http//:answers.unity3d.com/…/component-makes-05k-gc.html
...then GetComponent() is using exception handling to handle something that is pretty darn normal - Dictionary (etc.) lookup. i.e. this isn't an 'exception'.
And if it's throwing exceptions, I'm not seeing them in my console or Editor log or the Profiler, with all verbose logging player settings on max - unless I'm missing something. So, please report the exception so we can find the problems in our/others code.
Unfortunately, GetComponent() is something people habitually call inside the high-frequency callbacks, like MonoBehaviour.Update(), instead of caching results, using serialized fields, etc. And there are numerous snippets on the web that lead them to believe that this is desirable/normal. Even more reason to make sure that the method family is as tight as possible.
I would urge the Unity folks to reconsider this behavior. At a bare minimum, the difference between runtime and editor behaviors needs to be documented and we need some logging to pester Devs into looking at their GetComponent() usage patterns.
- thanks
zadr
Mar 30, 2016 18:27
public static class GameObjectExtension
{
static List<Component> m_ComponentCache = new List<Component>();
public static Component GetComponentNoAlloc(this GameObject @this, System.Type componentType)
{
@this.GetComponents(componentType, m_ComponentCache);
var component = m_ComponentCache.Count > 0 ? m_ComponentCache[0] : null;
m_ComponentCache.Clear();
return component;
}
}
Stephan_v
Sep 04, 2014 21:53
@LJMEIJER, my mistake you are correct. Verified that GC alloc is 0 bytes on iOS for GetComponent.
Cheerio
Aug 23, 2014 06:33
If calling GetComponent allocates because it is considered unexpected behavior when a component does not exist, would it instead be possible to add a "HasComponent" or a "TryGetComponent" method? I often use GetComponent to check for the existence of a component and adding either of these functions would allow me to check for existence without causing any memory allocation.
Lucas Meijer
Aug 06, 2014 13:56
Hey Stephan_V, I'm looking at the sourcecode here, and the code that generates that wrapper is ifdeffed out in everything but editor builds. I very much suspect you're crashing because of something else. If anybody is seeing GetComponent on a non existing component (or on anything for that matter), make any allocations outside of the editor, please file a bug with a reprocase (and post the case# here as a comment plz), and I'll check it out right away.
superpig
Jul 18, 2014 14:07
This did come up before and it turned out that there is some behaviour here that is *only* in the Editor - a wrapper object is created as part of making MissingComponentException work, but in a build the wrapper isn't created (and you just get a NullReferenceException instead).
Can anyone confirm that this is actually happening in builds? If so then it's something new...
Stephan_v
May 12, 2014 21:09
This was actually triggering a crash on iOS for me. NGUI uses GetComponent() extensively on disable/enable of UI Panels. When a UI Panel with many children was enabled/disabled several times before the GC, it created enough garbage (~20MB) to crash the app.
alan-lawrance
Apr 28, 2014 09:36
Verified this occurs on 4.3.4. The GC Alloc size I am seeing is large (0.6KB) each time GetComponent() is called and returns null. This can add up fast.