Jump to content
  • Advertisement
  • 10/26/19 05:57 PM

    Unity
    Unity UI Profiling: How Dare You Break My Batches?

    General and Gameplay Programming

    Ruben Torres

    [The original post with its formatting can be found at the Unity UI Profiling entry]

    You spend an infinite amount of time optimizing your Unity UI. But, all it takes to really screw up performance is a sneaky modification on a tiny attribute of an almost invisible Canvas UI element. And when that happens, not even Unity UI Profiling will save you from dropping frames. Are you ready for the road ahead?

    This is what happened in my last project...

    I worked hard to optimize the several UI panels of our port to Oculus Quest. This was mostly about reducing the overdraw level to an acceptable amount to make sure the GPU would be all comfy with the real 3D rendering.

    So I worked on Unity UI Optimization for at least a month and made pretty damn good progress.

    At some point, it was so well optimized that the GPU timings were barely moved by the UI. The opaque UI shading techniques I applied compensated most of the overdraw caused by UI Layering (elements drawn on top of other elements).

    Unity UI Profiling Extended - Thumbnail

    There I was, with a super optimized hybrid UI system that effectively occluded the 3D elements drawn behind it.  It became very easy to discard the rendering of these occluded fragments.

    However, I was far away from being done...

    When I hooked the Unity UI Profiler, one thing caught my attention.

    I saw an overwhelmed CPU taking over 1 ms per frame on UI rendering. That's a hell lot of time for a platform that gives you a budget of 13 ms for the whole game execution: physics, logic, 3D rendering, input, VR, networking are all in the same bucket.

    And I've seen cases where UI kills CPU performance even more.

    Unity UI: Expensive Build Batches

    Unity UI: Expensive Build Batches

    And that is the thing: UI can be optimized to be GPU-friendly, but that doesn't directly translate into being CPU-performing.

    In fact, CPU and GPU have very different tasks to accomplish in Unity UI Rendering. No wonder, I suggest you approach CPU and GPU optimization very differently, as seen in my previous blog post about Unity UI Optimization.

    Doing more of Unity UI Profiling showed me the obvious problem: the UI was constantly being re-created every single frame, i.e. there was a Canvas Rebuild happening every frame.

    A constant hit of 1 ms on the CPU... ouch.

    But why would Unity do this to me?
    I thought Unity cached the UI Canvases...

    Actually yes, that is correct. Unity effectively caches the canvases to make sure they are built just once.

    The problem arises, though, when you change the properties of any of the UI elements of the canvas, such as a color, a position and so on.

    That means, all animations we love, such as button hover effects, are killing your performance and you might not know it.

    When UI property changes happen, Unity does the famous Canvas Rebuild that will crush your game's performance.

     

    A Unity UI Canvas Rebuild makes Unity iterate over all UI elements of that Canvas to generate an optimized list of draw calls (a set of vertices, colors, materials, etc.). And Canvas Rebuilds take longer than a Seat Panda doing a 0-60 mph test.

    That said, once you've acknowledged you suffered from constant UI Canvas Rebuilds, the natural question to make is...

     

    Why am I suffering the Canvas Rebuilds and what can I do about them?

    ​Answering that innocent question led me to spending 5+ hours researching this topic and empowering the Unity UI Profiler.

    Let's see how.

    Quick Navigation (they all redirect to the original blog page)

    1. Unity UI Profiling: All Good, until...

    2. Unity UI Profiling: A wild Canvas Rebuild appears!

    3. Finding the Saboteur: a politically incorrect brute-force approach

    4. Bonus: Augmenting the Unity Profiler for UI Optimization

     

    hi-tech-ui-red.jpg

    1. Unity UI Profiling: All Good, until...

    Let's say we have a weirdo of a UI in front of us.

    That UI is barely doing anything but sitting there, being annoying to the player who just want to see something through it.

    As a collection of 350+ images using a Grid Layout Group, it (miserably) looks like this:

    Unity-UI-Profiling-Example

    Unity UI Profiling Example

    And that's fine, even if it contains 350+ images. They will normally be rendered in just two draw calls, as there are two unique images that are not atlased in a sprite atlas.

    Effectively, I can see in the profiler there's almost no overhead on the CPU side. Most of the time we're under 0.01ms, which is pretty damn good.

    Unity UI Profiling: Sneaky Spike

    Unity UI Profiling: Sneaky Spike

    (...Most of the time)

    ​Wait, what was that CPU spike at the end of the graph?

     

    hi-tech-ui-blue.jpg

    2. Unity UI Profiling: A wild Canvas Rebuild appears!

    What has just happened there at the end of the Unity Profile? The Unity UI CPU cost has more than doubled in just a second, how weird.

    I want to play a game

    Find the two differences in the samples below (you may want to click on them for zooming in).

    Unity UI Profiling: Cheap Canvas

    Unity UI Profiling: Cheap Canvas

    Unity UI Profiling: Canvas Rebuild

    Unity UI Profiling: Canvas Rebuild

    I'll give you five seconds to find it out.

    5, 4... Ok here's a hint to make it easier:

    Unity UI Profiling: Canvas Rebuild Overhead

    Unity UI Profiling: Canvas Rebuild Overhead

    Yikes!

    PostLateUpdate.UpdateRectTransform and UGUI.Rendering.UpdateBatches really wanted to take all the highlight in today's show.

    What do these regions do?

    The first, UpdateRectTransform, implies that a transform of a specific object has changed, and therefore Unity has to run some expensive logic to keep visuals coherent. We don't know whether it was a position, a rotation, a scale or any other of the RectTransform properties.

    Heck, we don't even know if it was just one attribute or all of them. Was it one object, or multiple? In any case, which ones? This is the problem: we do not know.

    The second cost, UpdateBatches, relates to the fact that the whole Canvas geometry has to be rebuilt. This process is famously known as a Canvas Rebuild. A canvas rebuild implies that Unity goes through all the Canvas hierarchy to generate a list of draw calls, so to speak. The vertices, indices, colors, uv's of all elements are computed and then a batching pass is done to we merge as many draw calls as possible to reduce the CPU overhead of issuing them to the graphics driver.

    Now we know what's going on, kind of. We're on the right track. But how do we go about avoiding these canvas rebuilds? What is causing them?

    We just need to find out more specific information...

    Summary

    the-gamedev-guru-logo-me-transparent-sma

    • An attribute change in a UI element will mark the element itself as dirty
    • A UI element can be totally dirty, but can also be partially dirty: vertices-dirty, layout-dirty, material-dirty. Partial dirty states are cheaper to recover from
    • Unity will rebuild canvases entirely, as soon as any of its elements are marked as dirty
    • Canvas rebuilds are expensive on the CPU, avoiding them is the key

     

    hi-tech-ui-sphere.jpg

    3. Finding the Saboteur: a politically incorrect brute-force approach

    We are still to give an answer to the following question:

    Who's triggering that sucky Unity UI Canvas Rebuild?

    It turns out, there's no fast way of finding that out, especially if your canvas hierarchy is immense.

    But, to start out, I'll show you the brute force approach for finding the source of UI Canvas Rebuilds.

    Unity UI Profiler Baseline with Canvas Rebuilds

    1. Keep the Unity UI Profiler recording

    Filter the metrics so you can focus on what is important: Rendering, Scripts, and UI.

    Keep an eye on the baseline to have a visual cue of your current baseline cost, which should include the expensive Canvas Rebuilds.

    Unity UI Profiler: Spike Found

    2. Deactivate UI Game Objects and compare

    Select a group of game objects and deactivate it.

    Compare the performance baseline.

    If the baseline didn't improve much, continue deactivating game objects till you see a significant improvement.

    Unity UI Profiler Spike: Saboteur Found

    3. Find out who is modifying its properties

    Now you managed to isolate which object is triggering your Canvas Rebuilds. But, who's actually causing those?

    Is it a script scaling it? Or maybe an animation changing its position?

    It helps to do a right-click on the RectTransform and press "Find References in Scene"

    Once you know who's causing the UI canvas rebuilds, do something about it, such as disabling animations or transforms.

     

    Ruben, how am I supposed to follow this approach in a huge UI hierarchy? Don't give me crap

    I told you it was going to be neither fast nor fun, but your players asked for it.

    That's the thing. Having a huge hierarchy in place is not ideal in the first place. Exactly those massive, deep hierarchies will make your Canvas Rebuilds incredibly expensive on the CPU.

    But big and nested UI hierarchies can (and will) happen, so expect canvas rebuilds to hit you where it hurts the most: your players' game-play experience.

    While the brute force approach helps finding the source of canvas rebuilds, this does not scale in the long-run.

     

    Becoming more professional about optimizing UI is what got me into creating a tool that would give me all the answers I needed to match my players' expectations...

    Canvas Rebuilds Profiling

    Canvas Rebuild Profiling

     

    4. Bonus: Augmenting the Unity Profiler for UI Optimization

    By now, hopefully, I stressed enough how frequent and impactful UI Canvas Rebuilds can be.

    These troll canvas rebuilds that infested my game stole 10% of my entire CPU budget!

    As we saw, there is a slow brute-force approach for finding the source of a canvas rebuild. Then, I hope you'll be able to do something about it, based on the strategies I posted on my Unity UI Optimization post (visit it, it's free, I promise!).

    But such as error-prone approach is a process a real guru would never settle for. You can literally spend days trying to avoid canvas rebuilds, but the moment you expect it the least, they'll come back just to disappear as soon as you attach the Unity UI Profiler.

    This becomes crucial if you're doing VR development. You don't want canvas rebuilds in your world-space UI. Like not at all. If you don't get rid of these, you're very much likely to convert your players into patients.

    I get it, I will get rid of the canvas rebuilds. But the Unity Profiler won't tell me much about those! What advice can you give me?

    I'm glad you asked. It turns out we can convince the Unity Profiler to give us useful information about who's messing with the performance of our UI.

    You and I can augment the functionality of the Unity UI Profiler. We do so by altering the Unity UI source code that is publicly available. Once you have the source code, you'll want to find the code functions where the Canvas Rebuilds take place. Then, all we need is some BeginSample and EndSample Profiler API magic.

    If you're running Unity 2019.1 or earlier, the Unity UI source code is available for free in their Bitbucket repository. You can follow their guide there to download, install and modify it.

    My suggestion? Use a newer Unity version, at least 2019.2.0. New versions of Unity include the UI source code by default, as the UI system is now part of the package manager. That's the hassle-free way of doing this.

    Here's a list of code regions I found during my investigations where you could add the Profiling API calls:

    Unity UI: Profiling Source Code

    Unity UI: Profiling Source Code

    Useful? Yes. 

    Artist/Designer-friendly? No.

    That's why I wrote a small open-source Unity Extension to enhance the Unity Profiler for you.

    Guru's Unity Profiler UI Enhancer

    The free tool will allow you to quickly switch over profiling modes to make sure the performance of your game is on top.

    The best part of the Unity Profiler enhancer? It just works outside of the editor, effectively replacing all the aspirins you've been taking while profiling your UI in Android and other platforms. 

    Here it is, all its power under your control with two simple buttons: 

    • Buff my Unity Profiler
    • Nerf my Unity Profiler.

    Grab it now here:

    Unity-UI-Profiler-Enhanced-CD-Front



      Report Article


    User Feedback


    There are no comments to display.



    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

  • Advertisement
  • Advertisement
  • Latest Featured Articles

  • Featured Blogs

  • Advertisement
  • Popular Now

  • Similar Content

    • By N1H1LU5_k
      Greetings. Thank you for opening this thread. Long post ahead. I am a High School student trying to get into game development. I would like to ask you a set of questions, but I think giving a context first will be the best. So, this is what's happening:
       
      In recent time, about 3 weeks ago, I started learning how to use Unity Game Engine and Blender. I always loved to draw and design all kinds of weapons, armors but also levels (unfortunately, all of those are on paper only, FOR NOW, of course) and when I started to think about how to apply this trait of mine, I concluded I could try creating a game. Since it's only been three weeks, my game-making skills are extremelly poor (as expected). Fast forward to yesterday. We were supposed to pick up a topic for our graduation thesis which we will hand in closely to our school-leaving examinations in year 2021. There is a TON of stuff to choose from. As long as it is part of IT, it's fine. And I chose to make a game. Well, it's more of a one level of a game in my case. More students before me have taken this topic and passed totally OK with Flappy Bird-style game they made. They were satisfied with it. I wouldn't be. I want this game to be best possible, that is why I also want to start working on it as soon as possible. In fact, I am starting right now, but I figured it would be better to ask here first. I have roughly 17 months to make a game worthy of passing. Of course, it could be some Flappy Bird. But I want to go further. Excuse me if this all sounds stupid, but I simply would not be satisfied with just any game I would make. I am well aware I won't be able to make a game like Battlefield alone, that there is a ton of people and budget behind such games. But I want it to be as best as possible.
       
      Now, my question is: What kind of game would I be able to make in this time of 17 months ? You have probably rolled your eyes after this question, don't worry, I understand how subjective the answer is. But I will at least try to state some metrics that can help with answer. I believe I have some fundamentals of programming, willing to learn the language needed (I believe in this case it's c#), I will be hooked on creating, animating and further improving 3D assets as needed for sure. I am able to dedicate at least 2 hours every day, a lot more so on weekends. I have to prepare for school and I also work, so that would be 2 hours of time on workdays right now. I would be able to get music and voice samples for characters in the game. 
       
      Here is my current plan. Please, if you see this as unreal to make in my deadline, tell me about it. I want to make one level of a FPS shooter, kinda sci-fi game with approximatelly 4-5 cutscenes and a small bossfight at the end of the level. Graphical quality would be that of a current CS:GO. Favored play-time would be, I think, around 15-20 minutes. Map would be a destroyed urban area. I have a lot of concepts (characters, weapons, rooms and so on) already drawn and if not, envisioned. If this is not possible, what would be the best game I would be able to make in 17 months ?
       
      Thank you for reading. Please, be honest. I know my idea can sound stupid, and answer I am looking might seem too subjective, but I want to get corrected if I am wrong with all of this. I highly value any reply that will be able to help in the slightest.
       
      Until then, have a nice day.
       
    • By Trexioas Xavier
      I want to know how would i go about making a 3D line renderer, it can be either a 3D or 2D-billboard line renderer. I don't want it to be static, i would like to add vertices to the line and extend it however i want to. To give an idea of what i want it to be/look like, Think of the Gauss Gun from Half life 1 and Half Life 2. I would want to make it reflect off the walls. I know i would need to do calculations to determine how to reflect off walls, i am just asking how would i go about making a 2D/3D line renderer. Please send me some online resources i can read upon.
      Thank you for your help!
    • By RoKabium Games
      Weapons - Magnacer is the first basic weapon that your Alien has equipped from the start. It shoots single bullets with a medium range that makes moderate damage to most enemies.
    • By CursedPhoenix
      I'm thinking on developing my own breeding game. Should be easy enougth to create the basic game mechanics and mostly the planning phase is done. I'll use "NimbleBit"s "Pocket Frogs" (https://en.wikipedia.org/wiki/Pocket_Frogs and https://play.google.com/store/apps/details?id=com.nimblebit.pocketfrogs&hl=de) as example, because my idea is in some ways quite similar. Android is the first platform I want to target, with optional expanding later to IOS and perhaps Windows.

      First Problem:
      I'm quite not sure about what language or engine I should use. I know this question is mainly based on opinion, but based on what I plan to do, is there an engine to prefer and why, or should I build it from scratch and wich language should I use then? At the moment my best bet would be on unity or python. Any suggestions here?

      Second (and most significant) Problem:
      I want to create a large amount  of - let's call it - monsters, that differs in color, pattern, color of the pattern and partly shape, but I don't get the trick behind it. So the question here is: How to create reusable monsters that differ in the above mentioned characteristics, with the lowest possible number of graphics.
      My thoughts and attempts on that topic: I looked at Pocket Frogs, and except shape they do exact the same with their frogs what I want to do. But I really don't get how they created over 38.000 (!!!) individual frogs, and the game still doesn't use that much space. I first tried to extract the graphics from the games files to puzzle together what they did. But I could not find them. However I think I figured out some parts of this secret just by looking at the frogs ingame: I think they used a basic frog model. 16 to be exact, to create 16 background frogs in all the colors. On top of them they just displayed the different patterns. But - and thats the mystery - the patterns are in different colors too and  I still dont believe they made 16*104=1664 different pattern graphics. So what trick am I missing here? Some kind of mask? Can I use the same technique to create different additional shapes for my monsters? And how did they made the feet moving. If the pattern on the feet are extra graphics, that would be another 1664 graphics.
      Any idea on how I can make this work, or on how did they make this work will be very appreciated! Thx
    • By JeremyAlessi
      In episode 12, Jeremy chats with Nathan Jester and Derek Hampton at Brown Chicken Brown Cow in downtown Hampton.  Nathan and Derek are local indie developers and long-time PixelFest participants. Nathan recently built a shoe-box arcade controller amongst a variety of gaming projects. Meanwhile, Derek talks Bouncy Bear and personal skill development.
       
       


      View full story
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!