While working on no signal, I ran into an issue where the game lags whenever the GUI changes.
After 20240529195943, I decided to implement a feature where the chat log changes between a non-corrupted version and a corrupted version whenever the corruption state changes. This was done by deleting all of the old nodes and generating new ones. However, this resulted in a significant lag of 2 seconds whenever this happened.
At first I thought this was due to the performance of my text corruption function but upon investigation, all of my scripts took a very small fraction of the processing time. However, the total processing time was still very large and I didn’t know where the time was being spent.
Doing a cursory search online, I found this topic on the Godot Discourse:
Answering my own question: I was able to tab into the Visual Profiler and figure this out but I had to wait a few seconds before data started appearing, which showed that bottlenecking was occurring on the GPU not the CPU. I was also able to get more information from going Project Settings → Advanced Settings → Print GPU profile, which made it obvious that most of the issue was in the “Render CanvasItems” step.
Some other issues I found that might be relevant, but I’m not convinced they are necessarily related:
- Large number of CanvasItems in the scene slow down input (godot/godotengine#56199)
- Poor performance of 2D Tree View with many items (godot/godotengine#70869)
Control::_size_changed()
is slower than necessary (godot/godotengine#86011)
It appears this problem only shows up in Godot 4.0 with the Forward+ renderer. In 3.0 or if you’re using the compatibility renderer, this specific performance issue does not appear to exist
Working off of this, I guessed that the performance issue was due to the time it took to lay out all of the controls in the UI. So, I simplified the chat log UI in several ways:
- Reuse controls when possible instead of creating new ones. It appears to be cheaper to change the text than to add a new control that has alternate text on it due to the reduced number of things that need to be considered during the layout function.
- Use less controls, especially containers, whenever possible.
These changes let me reduce the time spent from 2 seconds to about 300 milliseconds.