Static UI Performance Improvements


#1

Hi developers,

As part of our ongoing effort at Roblox to make games run smoothly across all devices, we’ve recently enabled some performance improvements for static UI rendering. Previously, Gui appearances were recomputed every frame. Now, Gui appearances are cached until they change. This means Guis now take less time to render if none of their descendants have changed since the previous frame.


An example Microprofiler capture of a place with hundreds of unchanging SurfaceGuis. The new system saves 1.9 milliseconds on my laptop. This improvement is even more significant on mobile devices.

A Gui’s appearance is cached until one of the following events occurs.

  • A descendant is added to the Gui.
  • A descendant is removed from the Gui.
  • A property of a descendant of the Gui changes.
  • A property of the Gui changes.

If any of these events occur, the Gui’s appearance will be recomputed the next frame it gets rendered.

I made a quick visualization of events that invalidate a Gui’s cached appearance. The red overlays indicate which object changed, causing the invalidation. The Purple outline overlay on the Gui indicates the entire Gui’s appearance has been recomputed.

Performance Tips

Currently, any change in any descendant of a Gui will invalidate the entire Gui’s appearance. We may make this more robust in the future. Consider separating mostly-static and mostly-dynamic UI into separate Guis so that the mostly-dynamic UI does not interfere with the mostly-static UI cache. Also consider avoiding frequently updating properties of non-visual descendants of Guis, for example Value on NumberValues.

Use the MicroProfiler to diagnose performance issues. Gui rendering has the label “GuiLayerCollector::render2dContext” and shows up under Pass3dAdorn and Pass2d. render2dContext will complete almost instantaneously for cached Guis.

To measure how well your Guis are being cached, you can write a script that listens to the events listed above that cause invalidation. You can use this method to make a visualization like the one in the video.

Also read about Quantum Gui. Quantum Gui is a separate optimization that caches the computed layout of a UI. There is another performance improvement related to checking if Guis need re-layouts on the way. This should further improve performance in places with dozens of Guis.


#2

Love to see it! Thanks… keep it coming :wink: :smiley:


#3

Thank you Roblox! This is a great feature you added! Now, Games will run smoothly!


#4

This is fantastic! Should see some really nice improvements in performance! Is this enabled globally or is this restricted to the new UI system and won’t work with blacklisted places?


#5

Wow this is some great stuff i’m glad they post this thanks.


#6

I’m ecstatic that this change is here to save on performance, should help mobile device performance a bit :smile:


#7

Definitely a breakdown! I hope it helps overall performance.


#8

Nice! Great feature.


#9

So basically when this new feature is live; when a GuiObject changes like a Text Box it will only render that change instead of rerendering all of the GuiObject inside the same LayerCollector ?


#10

There should definitely be a performance increase. Re-drawing the GUI if it’s static is a complete waste of resources. Thanks for the update!


#11

Does this improvement also act as a solution to another issue wherein the Gui section of memory would constantly move at a rate of change upward, or is this only related to performance for rendering Guis?


#12

Will help plenty of lower-end devices with some games that lag a little. Keep the updates rolling in! :wink:


#13

This is enabled everywhere right now.

Not quite. Changing any GuiObject causes the entire LayerCollector’s appearance to need recomputing.

Basically, we were previously iterating through all GuiObject Instances and generating their rendering geometry every frame. Now, we iterate through all GuiObject Instances and generate a compact representation that has all of the information we need to create the Gui’s rendering geometry. This is an array of all the rectangles that appear on the screen and their colors, textures, etc. If a Gui hasn’t changed since the previous frame, we just draw the rectangles in the array instead of visiting every GuiObject descendant and regenerating its rectangles. The new method is more cache coherent and avoids doing redundant work to figure out what a GuiObject should look like based on what kind of GuiObject it is and what its property values are.

This is just a performance improvement. Is there a bug report thread for what you’ve described?


#14

This is the most recent case I’ve known of a Gui memory leak (not in Platform Feedback):


#15

Great change! Will be a good improvement for performance.


#16

Love the new improvements, especially towards the mobile platform! Keep it coming Roblox! :wink:


#17

This is awesome.

EDIT: Does this mean that an overall “transparency modifier” (like this suggestion) is possible now?

EDIT#2: Ah, upon reading this explanation it doesn’t seem like it is :frowning:


#18

Neat! Will the optimizations that the chat window in the mobile app uses that were mentioned at RDC be added? Like the 1fps optimization?


#19

Awesome improvements! :+1:


#20

This will make a significant performance boost in my games! Great work team! :+1: