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

Profiling

-

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.

Comments (9)

  1. shubhamswaraj2021

    Aug 18, 2020 16:47

    good one <a href="https://www.lyricsauto.com">lyricsauto</a>

  2. 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

  3. 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;
    }
    }

  4. Stephan_v

    Sep 04, 2014 21:53

    @LJMEIJER, my mistake you are correct. Verified that GC alloc is 0 bytes on iOS for GetComponent.

  5. 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.

  6. 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.

  7. 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...

  8. 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.

  9. 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.

Add comment

Log in to post comment

All about bugs

View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.