Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Labels with lots of text very slow in Godot 4 #77268

Closed
heroofhyla opened this issue May 20, 2023 · 12 comments · Fixed by #77280
Closed

Labels with lots of text very slow in Godot 4 #77268

heroofhyla opened this issue May 20, 2023 · 12 comments · Fixed by #77280

Comments

@heroofhyla
Copy link

Godot version

4.0.3 stable

System information

Windows 10, i5 8600, RTX3060, 64 GB ram

Issue description

In Godot 4, labels with lots of text cause scenes to load extremely slowly, both in the editor and in-game.

I measured a few game starts with different amounts of text in a label:

Text length Game start time
11323 2.33
22693 7.93
34064 19.69
45431 40.59

In Godot 3, the startup times for all test lengths was almost instantaneous.

The text I used was multiple copies of the license agreement for Google's Roboto font. A "credits" page on a game could easily get well above this length.
Looking at a scatter plot with a best fit, it's pretty clearly increasing at around n^2:

image

Results are the same whether I'm using the built-in font or a custom font, and results are similar across all renderers. Settings like text wrapping don't seem to affect it either.

Steps to reproduce

Create a scene, add a label to that scene, and fill the label with a large amount of text. Try to launch the game and load that scene.

Minimal reproduction project

Godot3LargeLabel.zip
Godot4LargeLabel.zip

@kleonc
Copy link
Member

kleonc commented May 20, 2023

cc @bruvzg ?

@Calinou
Copy link
Member

Calinou commented May 20, 2023

Can you check this when using the fallback text server? To do so, compile the editor with the module_text_server_adv_enabled=no module_text_server_fb_enabled=yes SCons options.

@Calinou Calinou added the bug label May 20, 2023
@AThousandShips
Copy link
Member

AThousandShips commented May 20, 2023

Can you compare it to using multiple labels totalling the same amount of text? (Both to pinpoint some details and for workarounds)

@Rindbee
Copy link
Contributor

Rindbee commented May 20, 2023

The size keeps growing to contain all visible text. Increase the height of one line each time.

godot/scene/gui/label.cpp

Lines 275 to 277 in 809a982

if (autowrap_mode == TextServer::AUTOWRAP_OFF || !clip || overrun_behavior == TextServer::OVERRUN_NO_TRIMMING) {
update_minimum_size();
}

godot/scene/gui/label.cpp

Lines 405 to 407 in 809a982

if (dirty || font_dirty || lines_dirty) {
_shape();
}

There seems to be a logic bug in the following code, it's not clear to me why there is a break, it doesn't seem necessary.

godot/scene/gui/label.cpp

Lines 291 to 296 in 809a982

for (int64_t i = lines_skipped; i < last_line; i++) {
minsize.height += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing;
if (minsize.height > (get_size().height - style->get_minimum_size().height + line_spacing)) {
break;
}
}

@MadFlyFish
Copy link

I hava a similar problem. It takes a lot of time when add_child a scene with labels.

@Rindbee
Copy link
Contributor

Rindbee commented May 24, 2023

I hava a similar problem. It takes a lot of time when add_child a scene with labels.

This issue does not occur if the initial size is specified to a large value (enough to cover all visible lines of text).

@heroofhyla
Copy link
Author

This issue does not occur if the initial size is specified to a large value (enough to cover all visible lines of text).

This is a great catch! I can confirm that it fixes the speed issue. It can be expanded to more complex cases as well. In my case I need the label to be inside a ScrollContainer, and I'm reading the text from files so I don't know exactly how large the label will be.
My scene structure looks like this:

CreditsScene
  ScrollContainer
    Label

I managed to find this solution, expanding off of yours:

  1. Set a custom_minimum_size for the label that is much larger than the text you expect to load
  2. Load the text from the file into the label
  3. Set the custom_minimum_size to 0,0.

Step 1 and 2 go in the Label's _ready function, step 3 goes in the CreditsScene's _ready. If you do it all in the same _ready function you don't get the performance improvement.

The Label's _ready looks like this:

func _ready() -> void:
	custom_minimum_size = Vector2(0,999999)
	text = "\n\n".join(TextFileReader.dir_get_all_text(source_dir))

and the CreditsScene's _ready looks like this:

func _ready():
	$ScrollContainer/Label.custom_minimum_size = Vector2(0,0)

@Calinou
Copy link
Member

Calinou commented Jun 18, 2023

I can't reproduce this on both 4.0.3 and 4.1.dev 33957ae with the linked MRP for Godot 4 (Linux). The label already appears to be sized to contain all lines of text, so it starts very fast.

@Rindbee
Copy link
Contributor

Rindbee commented Jun 18, 2023

I can't reproduce this on both 4.0.3 and 4.1.dev 33957ae with the linked MRP for Godot 4 (Linux). The label already appears to be sized to contain all lines of text, so it starts very fast.

Maybe your computer is too powerful. 😄

@Calinou
Copy link
Member

Calinou commented Jun 19, 2023

Maybe your computer is too powerful. 😄

I mean, I don't even see a difference of 0.1 seconds between master and this PR. While I do have a i9-13900K (which is very fast at single-thread computations), it's not so fast as to make the potential performance difference unnoticeable. IIRC, it's roughly 3-4 times as fast as most Kaby Lake mobile CPUs in terms of single-thread performance. I think something else is going on here.

@Rindbee
Copy link
Contributor

Rindbee commented Jun 19, 2023

diff --git a/game.tscn b/game.tscn
index 1953d25..9d20ed0 100644
--- a/game.tscn
+++ b/game.tscn
@@ -13,7 +13,7 @@ layout_mode = 0
 offset_left = 16.0
 offset_top = 13.0
 offset_right = 1133.0
-offset_bottom = 623.0
+offset_bottom = 15639.0
 text = "Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/

I'm guessing the file might have been modified. If it is modified as above, there is no difference.

@Calinou
Copy link
Member

Calinou commented Jun 19, 2023

I'm guessing the file might have been modified. If it is modified as above, there is no difference.

This was indeed the issue. If I ensure this change isn't made to the scene file, I can reproduce this issue. See #77280 (comment) for results.

Apologies for the false alarm 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants