Search Unity

[5.2] MaskableGraphic performance OnEnable(), OnDisable()

Discussion in 'UGUI & TextMesh Pro' started by cowtrix, Sep 9, 2015.

  1. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    322
    Hey folks. Our UI has seen some major spikes since upgrading to 5.2 from two functions - MaskableGraphic.OnEnable() and MaskableGraphic.OnDisable(), both coming in at a whopping 51ms. There is also a 2.1 MB allocation in OnEnable(). This is occuring through GameObject.SetActive(). This did not occur in 5.1.

    Is the intended design paradigm here to just make UI elements invisible, rather than disabling the GameObject? Are we in the wrong here, or is this an actual issue?
     
  2. Stephan-B

    Stephan-B

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    Out of curiosity, how many text objects do you have in your scene?
     
  3. darkForester

    darkForester

    Joined:
    Sep 19, 2013
    Posts:
    80
    Unity 5.2.0f3 - Windows 10

    We are seeing similar issues arriving from the ScrollRect.LateUpdate & CanvasUpdateRegistry.PerformUpdate, these are higher in the chain but most certainly causes spikes. I have attached some samples from the profiler.

    After reviewing much of the UI library source code, there are places where GetComponent is also being called during layout phases. (Which seems like a big no-no in the performance arena).



    Notice the garbage collection from the MaskableGraphic.OnEnable as was mentioned by the OP.



    Below is an example of code that could be optimized by caching the values. (Notice the GetComponent call, we should cache this returned value somewhere so it doesn't kill performance when a fair amount of UI is present.

     
    Last edited: Sep 9, 2015
  4. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,225
    Can I get some repro projects and bug ID's for this. It doesn't seem related to batching but we made changes to masking which might have regressed some performance.
     
  5. darkForester

    darkForester

    Joined:
    Sep 19, 2013
    Posts:
    80
    I have attached a simple project with one scene. I have designed a ScrollRect based UI will roughly 20 elements. This is a rather simply UI compared to the complex scenes that are possible.

    * This does not reproduce the MaskableGraphic.OnEnable. I believe in order to reproduce that, you need to add a mask to each child of the already-masked scroll rect.

    Steps to Reproduce on v5.2.0f3
    1. Start the scene, notice the huge spike from ScrollRect.LateUpdate
    2. Drag the ScrollRect, notice the huge garbage collection.
    Let me know if you need anything else.
     

    Attached Files:

  6. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,225
    I've spent the day doing a pass on the GC pressure issues in the layout system. It should be much better now. One thing to not is that currently text in layout isn't as efficient as it probably should be. Getting this into a patch release ASAP.
     
    laurentlavigne and wikmanyo like this.
  7. darkForester

    darkForester

    Joined:
    Sep 19, 2013
    Posts:
    80
    Tim,

    Thanks for the quick turn-around we will await the patch release and let you know how it goes.
     
  8. Tim-C

    Tim-C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Posts:
    2,225
    I think p1 is already out to out QA, so it will likely be in p2.

    Side note: We have a bunch of automated testing, for both performance and regressions. When we discover something like this that missed the tests we add a new test to cover the area. If you have access to the beta's please please try loading your projects in them and giving it a quick test. We put barely any code into 5.2 over the last month and had very few bugs coming in. We would have loved to have known about this a few weeks ago so we didn't ship with it.
     
    laurentlavigne likes this.
  9. iivo_k

    iivo_k

    Joined:
    Jan 28, 2013
    Posts:
    314
    Maybe that's part of the problem. Personally I didn't even bother with the 5.2 betas since every release had some known or immediately reported major issues that were deal breakers for me. Then suddenly you were going with release candidates, which also had deal breaker known issues. Seems I'll be waiting for patch 2 or something before I'll even try to upgrade the project. Maybe the deadlines were too tight, but I think there should've been a few more beta releases.
     
    BenouKat and ortin like this.
  10. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    322
    Hey Tim, apologies for not being able to post a repro, it seems to be pretty slippery. We've rolled back to 5.1.3 for now, and I currently don't have any more time to spend on it.

    I think the problem is that many of these bugs don't emerge except in more complex projects (like ours) which are also under a lot of time pressure. So, we simply don't have the time and resources to do this Unity bug testing, we're swamped enough as it is with non-Unity bugs.
     
    BenouKat likes this.
  11. BenouKat

    BenouKat

    Joined:
    Feb 29, 2012
    Posts:
    222
    I can confirm that for big projects the Unity betas aren't possible, even if we're are very interested to improve the engine.

    The two main reason are given by my 2 predecessor posters : Major issue is a deal breaker, and no time to port the project on beta for just testing. We do it with small project when we got some, but not with the main and big one.

    Maybe you guys should ask some dev to share their "big" project with you, you'll be able to test it on your side during development or alpha. Because it's something we - and I think other dev too - don't do sponteanously at work. I already "lost" a day to upload projects and report bug on 5.2, and even if I'm really glad to help you, it still a day that I lost. And I can't do this often, like in beta phase.

    For example we'll be totally open to share you our main project (2.5Go of love) to you for checking everything you think it's wrong, not for a specific bug. Maybe you should add this on your beta programs.
     
    Last edited: Sep 14, 2015
  12. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    HI, we are having troubles with MaskableGraphic.OnEnable causing bad Garbage Collection while loading a new level (Unity 5.2.2f1).

    Profiler:

    Screen Shot 2015-11-12 at 12.28.13 PM.png
     
  13. XuTenTen

    XuTenTen

    Joined:
    Apr 30, 2015
    Posts:
    14
    Hi,Tim. I'm also using Unity 5.2.2f1 and got a great GC spike on Canvas.SendWillRenderCanvases and MaskableGraphic.OnEanble, Text.OnEnable.

    I think it is a bug should be solved ASAP. I've found many other guys got this problem.

    Profiler is in attach
     

    Attached Files:

  14. Grhyll

    Grhyll

    Joined:
    Oct 15, 2012
    Posts:
    119
    Hi, I'm experiencing high alloc for Text.OnEnable as well...
     
    radiantboy likes this.
  15. Alic

    Alic

    Joined:
    Aug 6, 2013
    Posts:
    137
    Still seeing this issue in Unity 5.3.1p1 on windows 7! TONS of garbage every frame.
     
  16. Paniku

    Paniku

    Joined:
    Apr 11, 2013
    Posts:
    24
    Having this issue as well!
     
  17. StayThirsty

    StayThirsty

    Joined:
    Jul 6, 2013
    Posts:
    42
    MaskableGraphic.OnDisable, EventSystem.Update still creating garbage on Android, Unity 5.3.21f Personal.... Coroutines also create garbage :(
     
  18. Azmar

    Azmar

    Joined:
    Feb 23, 2015
    Posts:
    246
    I noticed this problem too a few months ago when GC allocations were incredibly high, I ended up rewriting my entire system to hide everything and just show it when I need it lol. I didn't realize this was a bad bug on Unity end. I would love to put back my system the way it was before! Please fix Unity!
     
  19. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    Just was about to write a thread about this. In my case I have 20 Objects parented to one master object.Each of this 20 objects have 10 UI images. When i disable and enable the master object i get 0.5MB garbage collection which is insanely huge in my opinion.
     
    Azmar likes this.
  20. sysameca

    sysameca

    Joined:
    Mar 2, 2013
    Posts:
    99
    Not to mention that on my real project it's worse- 15 objects with only 8 images for each - 0.5MB - Unity 5.3.1 prob.png
     
    Azmar likes this.
  21. Bravo_cr

    Bravo_cr

    Joined:
    Jul 19, 2012
    Posts:
    148
    Please fix this once for all. uGUI perforce is extremely bad.... Lot's of draws (please allow us to manually choose rendering order), huge GC for really simple things, etc etc,
     
  22. Bravo_cr

    Bravo_cr

    Joined:
    Jul 19, 2012
    Posts:
    148
    I just see the following in the profiler:

    Unity troll method name.png

    I love the "Troll Method" called "ApplyShadowZeroAlloc()" which allocs almost 50k for applying a shadow to a text of 10 characters.
     
    Grhyll and Azmar like this.
  23. dhkd1157

    dhkd1157

    Joined:
    Nov 13, 2012
    Posts:
    2
    It happen in 5.3.3p1.
     
  24. Alic

    Alic

    Joined:
    Aug 6, 2013
    Posts:
    137
    On my end it DOES NOT happen in 5.3.3p1. I was getting 500kb or more allocations per frame in MaskableGraphic and CanvasUpdateRegistry.PerformUpdate, and now I get absolutely NO allocations due to Unity UI. So, at the very least the issue seems to be much improved in 5.3.3p1. (And in my case, it is 100% fixed -- cheers Unity guys and gals!)
     
  25. RV1

    RV1

    Joined:
    Nov 18, 2012
    Posts:
    68
    I have just upgraded to Unity 5.3.3p1 and I am still seeing allocations on Text.OnEnable, Text.OnDisable, MaskableGraphic.OnEnable and MaskableGraphic.OnDisable.

    For the Unity devs, I have been looking over the code for Text.OnEnable trying to figure out where the allocations/spikes are coming from and I have a few suggestions:

    In FontUpdateTracker.cs:

    - In TrackText and UntrackText you use Font.textureRebuilt += RebuildForFont. This generates garbage because under the hood its doing new Action<Font>(FontUpdateTracker.RebuildForFont). You can prevent this by caching the delegate.

    - In UntrackText, it looks like when a list for a font is empty, you remove it from the dictionary. Assuming I am not misunderstanding what a Font object is and that is only one object per font used by a project, then it seems unneccessary to remove the entry from the dictionary since you are throwing away allocated List<Text> objects. Instead you can just check if the list count is zero when skipping a rebuild for a font. You are already querying the dictionary to see if an entry for that font exists anyway.

    - Random access removals from lists with large amounts of entries can be quite expensive (this may contribute to the spikes people are seeing). This is because it is using Array.Copy to shift elements that were after the removed entry. In this situation LinkedList<Text> may be a better alternative provided you cache LinkedListNode<Text> for the Text object. That way when you untrack a text object, you can remove it from the linked list directly without any allocations or need to search.
     
  26. dhkd1157-dalcom

    dhkd1157-dalcom

    Joined:
    Apr 16, 2014
    Posts:
    12
    That’s weird. I don’t use Unity UI Texts, and everything I did was enabling and disabling the SetActive() of MaskableGraphic objects that were created in advance, so that there won’t be any GC spark.

    When the MaskableGraphic.OnEnable was used GetComponent was called, and GC sparks (0.5 kb) occurred. I’m currently using Unity 5.3.3p1., and this happens every time.

    I can attach some samples from the profiler if you want to take a look into it.
     
  27. Bravo_cr

    Bravo_cr

    Joined:
    Jul 19, 2012
    Posts:
    148
    I Still see this on 5.3.3p1 even if I set all maskable graphics to false in the awake. Each time I enable or disable the GameObject you have the GCAlloc.
     
  28. deliriumz

    deliriumz

    Joined:
    Aug 22, 2012
    Posts:
    34
    5.3.4f1 still happens.

    - GameObject.SetActive
    -MarkableGraphic.OnEnable (2.9kb GC)
    -Text.OnEnable
    -which in turn calls MarkableGraphic.OnEnable (4.8kb GC)

    On mobile this causes quite a noticeable spike each time this screen is called. I usually send in separate projects for bug reports, but this one is a bit of a hassle to send in due to time constraints.

    here is the profiler which shows a breakdown. note, the screen is already instantiated, which is why I do not expect to be seeing a spike.

    (for some reason it won't show it through the image displayer, so here is the link to it instead)
    http://postimg.org/image/jaapp2ry9/

    Update:

    After looking through the UI code on bitbucket, I reckon it will be coming from the MaskUtilties func which is called from the MaskableGraphic OnEnable:

    Code (CSharp):
    1.         public static RectMask2D GetRectMaskForClippable(IClippable transform)
    2.         {
    3.             var t = transform.rectTransform.parent;
    4.             var components = ListPool<Component>.Get();
    5.             while (t != null)
    6.             {
    7.                 t.GetComponents(typeof(RectMask2D), components);
    8.                 for (var i = 0; i < components.Count; ++i)
    9.                 {
    10.                     if (components[i] != null && ((RectMask2D)components[i]).IsActive())
    11.                     {
    12.                         var result = (RectMask2D)components[i];
    13.                         ListPool<Component>.Release(components);
    14.                         return result;
    15.                     }
    16.                 }
    17.  
    18.                 var canvas = t.GetComponent<Canvas>();
    19.                 if (canvas)
    20.                     break;
    21.                 t = t.parent;
    22.             }
    23.             ListPool<Component>.Release(components);
    24.             return null;
    25.         }
     
    Last edited: May 18, 2016
  29. toggiee

    toggiee

    Joined:
    Jan 5, 2012
    Posts:
    7
    I have same issue in 5.3.5f1.
     
    Paul-Chen and leni8ec like this.
  30. Paul-Chen

    Paul-Chen

    Joined:
    Feb 25, 2016
    Posts:
    6
    This bug was first posted in Jan. But until now the status is still Fixed in future release. I think the Unity team did not seriously deal with it. I have to add a CanvasGroup component to what I want to hidden and change it's alpha to zero. But this won't update the layout properly.
     
    conondev likes this.
  31. conondev

    conondev

    Joined:
    Jun 9, 2016
    Posts:
    24
    For now, I have to fix myself (from Unity UI repo on Bitbucket).
    Use these patched files if it works for you, not perfect but much better than before.
     

    Attached Files:

    DungDajHjep likes this.
  32. Paul-Chen

    Paul-Chen

    Joined:
    Feb 25, 2016
    Posts:
    6
    Great work! For me, this issue causes my battery drain. You simplified some code we don't need. But I have to compile the source code myself, is it?
     
  33. conondev

    conondev

    Joined:
    Jun 9, 2016
    Posts:
    24
    Yes, just follow the instructions of README
     
  34. Paul-Chen

    Paul-Chen

    Joined:
    Feb 25, 2016
    Posts:
    6
    I'll try. Thank you.
     
  35. Paul-Chen

    Paul-Chen

    Joined:
    Feb 25, 2016
    Posts:
    6
    Unity team seems to fix the problem in 5.4.
    • UI: Improved performance of MaskUtility functions.
     
  36. deliriumz

    deliriumz

    Joined:
    Aug 22, 2012
    Posts:
    34
    Unless I'm being stupid, it is still very much happening on the latest version. Every enable/disable I see text components churn out around 1.1kb of allocation. If I disable a section of a UI screen with 5 text elements, that is 5Kb instant. If I instantiate a new UI screen ( which is pooled, so it's already ready to go ) I get some crazy allocations at times.
     
  37. Green-Sauce-Games

    Green-Sauce-Games

    Joined:
    Mar 27, 2014
    Posts:
    71
    I have the same problem um Unity 5.4p3.

    It took me 200ms when Activating a ScroolRect with GridLayoutGroup and 100 items
     
  38. DungDajHjep

    DungDajHjep

    Joined:
    Mar 25, 2015
    Posts:
    202
    Thanks you but where i can find Readme ?
     
  39. conondev

    conondev

    Joined:
    Jun 9, 2016
    Posts:
    24
    DungDajHjep likes this.
  40. DungDajHjep

    DungDajHjep

    Joined:
    Mar 25, 2015
    Posts:
    202
    Hi @conondev , i copy your script to Unity-Technologies-ui folder and complier it , I copy Output\UnityEngine.UI.dll to Editor\Data\UnityExtensions\Unity\GUISystem but nothing happen ?
    p/s : test on device and editor
     
  41. conondev

    conondev

    Joined:
    Jun 9, 2016
    Posts:
    24
    If you switch "Deep Profile" on, you will see that alloc come from the initialization of the cachedTextGenerator of the Text, this is another thing (and should be initialized once, when you disable and enable again, there will be no more alloc for this).
    My patched files fixed another thing, related to FontUpdateTracker (even when you disable and enable again, alloc still happens). I just optimized this one only.
     
    DungDajHjep likes this.
  42. conondev

    conondev

    Joined:
    Jun 9, 2016
    Posts:
    24
    I have found this recently: https://unity3d.com/learn/tutorials/topics/best-practices/guide-optimizing-unity-ui
    Especially this section: https://unity3d.com/learn/tutorials/topics/best-practices/other-ui-optimization-techniques-and-tips.
    We all know that we can not enable/disable CanvasRenderer by script (no API related to this), this made me confused. Then I try enable/disable the Canvas instead. But sad, when enable/disable a Canvas, it will trigger the call to OnCanvasHierarchyChanged on MaskableGraphics, and this is really heavy.
    (this is captured on Editor)
    upload_2016-9-12_12-44-38.png

    So it's not really optimized yet. Have you ever tried this?
     
  43. mikael_juhala

    mikael_juhala

    Joined:
    Mar 9, 2015
    Posts:
    247
    Try adding a CanvasGroup into the same GameObject as the Canvas and then simply set alpha to 0 (and probably stop blocking raycasts). Shouldn't that let the Canvas keep its VBO data?
     
    conondev likes this.
  44. conondev

    conondev

    Joined:
    Jun 9, 2016
    Posts:
    24
    This is a good hint! Thank you.
    I tested, and switching CanvasGroup's alpha between 0 and 1 does not cause any heavy operations.
    I should use this solution for my project for now.
     
  45. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    VIDEO HERE
    Can anyone explain to me why I am getting 2k GC spikes when I move my mouse across UI?

    When I actually click on those UI, I get GC spike with maskgraphic.ondisable() as well.

    Using Unity 5.3.4.1
     
  46. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Older releases of Unity will get bug fixes at a slower rate from more recent releases, so you might want to check to see if your issue is fixed in 5.4 or 5.5
     
  47. xahei

    xahei

    Joined:
    Sep 22, 2014
    Posts:
    8
    I'm still seeing this issue in 5.5.0f3.
    MaskableGraphic.OnDisable causes GC and performance spikes.
     
    IcyHammer and leni8ec like this.
  48. IcyHammer

    IcyHammer

    Joined:
    Dec 2, 2013
    Posts:
    71
    MaskableGraphic.OnDisable is still present in 5.5.1.
     
  49. unormal

    unormal

    Joined:
    Jan 10, 2012
    Posts:
    65
    Seeing it in 5.5.1f1 as well.
     
  50. mrm83

    mrm83

    Joined:
    Nov 29, 2014
    Posts:
    345
    Anyone using 5.6 and noticed that this problem is 100 times much worst in 5.6 than in 5.4?