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:

shinyu6:

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:

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.