Search Unity

OnGUI performance

Discussion in 'Immediate Mode GUI (IMGUI)' started by Molix, Jan 26, 2010.

  1. Molix

    Molix

    Joined:
    Apr 24, 2009
    Posts:
    92
    Thanks to the handy dandy new profiler, I can see that our GUI code is taking up a lot of time - about 16ms per frame...ouch.

    I thought I must have buried some logic in there that shouldn't be there, but all of the functions that are taking up the vast majority of the time are internal ones that I do not call directly.

    Obviously I call them indirectly though, so I'd would like some advice on what I can/should be doing to reduce the time taken in these functions:

    GUI.Repaint->GUIUtility.EndGUI()
    GUI.Repaint->GUIUtility.BeginGUI()
    GUI.ProcessEvents->GUIUtility.EndGUI()

    Also, I have noticed there are spikes every 4-5 frames in:
    GUI.Repaint->GUIUtility.EndGUI->GC.Collect

    What can I do differently in my code to reduce those?
     
  2. Molix

    Molix

    Joined:
    Apr 24, 2009
    Posts:
    92
    Put another way: What do these functions do?

    GUI.Repaint->GUIUtility.EndGUI()
    GUI.Repaint->GUIUtility.BeginGUI()
    GUI.ProcessEvents->GUIUtility.EndGUI()
     
  3. Paul Usul

    Paul Usul

    Joined:
    Jul 30, 2009
    Posts:
    49
    Wow 16 ms is really a lot. But you should still remember that the computer testing has every thing to do with the problem. So are you testing on your lowest denominator? or on your high end work station :/

    Is it possible to get a screenshot? It could be that you are just using a lot of gui..

    All that said, I have noticed that GUILayout is quite expensive to use. Compared to screen relative GUI with out the use of BeginGroup.

    I personally always prototype with GUILayout and then implement the final result with clean GUI when possible.

    About the GC collect, you can remove a lot of that by caching styles, rects and other mics classes. Of course it's not always possible, but it makes the garbage collection faster.

    Hope I helped in some way, felt like I just rambled, :S ..
     
  4. Molix

    Molix

    Joined:
    Apr 24, 2009
    Posts:
    92
    Thanks for the reply, it does help a bit. I assume by "cache the styles" you mean maintain a reference to them between calls so they are not created and destroyed? I guess in general anything created in OnGUI (including Rects?) would contribute to that, but I'm seeing 3-4ms spikes, so I thought it might be something else.

    I've attached a couple shots of the profiler. The first is with an "average" frame, and the second with a spike.
     

    Attached Files:

  5. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    that are by far too many ongui functions
     
  6. Molix

    Molix

    Joined:
    Apr 24, 2009
    Posts:
    92
    Could you elaborate a bit? If I move all the OnGUI code to a single/fewer OnGUIs, but it is still the same amount of code, what is going on that will make that so dramatically faster? i.e. why are 2 calls with 1/2x the code so much slower than 1 with 2x the code? (I'm assuming since we're talking about milliseconds here that the overhead of a single function call is negligible).
     
  7. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    basically each ongui function is called multiple times per frame. once for rendering and x times for all x events that might or might not happen
     
  8. Molix

    Molix

    Joined:
    Apr 24, 2009
    Posts:
    92
    I understand, but even the overhead of 200 function calls wouldn't add up to 18 milliseconds. You may be right that there are too many, but what else is going on that makes it so much different?
     
  9. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    usage of GUIUtility does according the profiler
     
  10. Molix

    Molix

    Joined:
    Apr 24, 2009
    Posts:
    92
    I appreciate you taking the time to respond.

    I meant the overhead of the call, not what happens in the call. I want to make sure I understand what you're saying:

    OnGUI()
    A
    OnGUI()
    B
    ...
    OnGUI()
    Z

    should be:
    OnGUI()
    A
    B
    ...
    Z

    And will save something on the order of milliseconds?
    Doesn't that seem unintuitive?

    What is happening in GUIUtility.EndGUI (which I do not call directly and is undocumented) that grows with apparently non-linear complexity in the number of OnGUI functions? Or is it something else? I'm just trying to understand before I embark on what amounts to a major overhaul.
     
  11. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    no idea what happens in the endgui directly but I would expect it to be the step that assembles all the meshes for the ui (due to the vbo mention) and event handling ...

    generally you should potentially not combine the ui but just disable all you don't need at the time (with that I mean the whole game object / component, not just have a switch in the functino)
     
  12. duke

    duke

    Joined:
    Jan 10, 2007
    Posts:
    763
    Cache Cull! Anything that doesn't change or doesn't change often should be member variables, and anything that doesn't render at all (be it a message box or an item in a list that isnt on-screen) should be culled and ignored by OnGUI.
     
  13. Paul Usul

    Paul Usul

    Joined:
    Jul 30, 2009
    Posts:
    49
    A note about gc, it is drastically reduced when deep profiler is on. Any one know why?

    The overhead does not add up to that many ms. Close rendering and memory windows and enable deep profiler. This should reveal the evil culprit. Besides what looks like a extensive use of GUILayout.
     
  14. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    337
    I, too, have noticed that OnGUI is far more expensive than it should be. ~30 GUI.Box's drops my framerate by 100 fps, and a single GUIArea and GUILayout with about 10 items drops it another 50. I'm fairly experienced with Unity GUI and I've cached and culled a lot, but it's still far too intensive...

    To combat this, I've developed my own system to detect button clicks and just use DrawTexture a lot, but I need the GUILayout for the automatic resizing. Anyone else experiencing precipitous speed drops of this nature?

    BTW, I have all my code in a single OnGUI loop. Perhaps more loops would initiate multi-threading? I'm not an expert on how that works, so I'm not sure.

    -CJ
     
  15. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Unity code will never run on multiple threads even if you had half a million loops and a peta core processor.

    The whole unity environment runs on a single thread (scripting, gui etc). The only things that run on own threads are potentially physics (unsure if PhysX in that old version was multithreaded) and your own threads naturally.


    And yes it drains a lot of performance, its commonly the major cpu time eater in my projects if I use it.
    Luckily I don't use it that commonly, I use GUIX which I have owned since the day of its release and I definitely don't regret it in any way :)

    given the performance GUIX has (significantly higher) in the same situations as the normal gui, it becomes clear that it is related to the fact that GUIX has per object even callbacks instead of doing bruteforce "event pumping" (as far as I understand you have 1 call to each ongui for each event generated ...)
     
  16. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    337
    Well that's not promising... Good thing it's only on mouse over that the GUILayout call kicks in. GUIX, hmm? I'll have to look into it.
     
  17. Lukas H

    Lukas H

    Joined:
    Jan 16, 2009
    Posts:
    394
    Do a search on GUIManager in this forum. You can create GUI's with it with a low performance impact. Originally it was created for the iphone but it works with the non iphone-Unity too :)
     
  18. cj-currie

    cj-currie

    Joined:
    Nov 27, 2008
    Posts:
    337
    Thanks, I will try that.
     
  19. JFo

    JFo

    Joined:
    Dec 9, 2007
    Posts:
    217
    Hi Molix, have you found any reason for GUI.Repaint eating the CPU time? We have exactly the same problem and thus interested, if there are anything we can do about it...

    GUIX is only a C# wrapper to the normal Unity GUI so I don't think it can be more efficient than
    using the normal GUI directly..

    BR, Juha
     
  20. Andrej-Vojtas

    Andrej-Vojtas

    Joined:
    Jan 12, 2009
    Posts:
    67
    Can someone elaborate on the GUIX performance gain? Too bad I have no option to test it myself (GUIX trial run out).
     
  21. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
  22. radiantboy

    radiantboy

    Joined:
    Nov 21, 2012
    Posts:
    1,633
    so is it better to just avoid ongui altogether? could just use textmesh pro to do same thing.