godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.42k stars 21.06k forks source link

Laggy Label with large amounts of characters #80127

Open EchoingLogos opened 1 year ago

EchoingLogos commented 1 year ago

Godot version

4.1stable

System information

Windows 11

Issue description

A common use case for a Label in some applications is to encapsulate it within a ScrollContainer, allowing the user to scroll through the entirety of the text. However, Godot does not permit this use case because the entirety of the text is processed every frame, so a Label with lots of text is unreasonably slow. Further, there does not seem to be a simple workaround to "hack" seamless scrolling into the application.

Any of the label settings or font settings do not noticeably affect the processing of the label. The label is just as slow with word wrap turned off, so it's not a word wrap processing issue. The only factor I could find that affected the time the label spent processing was the amount of text, which sounds like undesirable behavior.

Steps to reproduce

  1. Create a Label
  2. Set the textproperty to a large amount of text
  3. Check the process time of the application

Minimal reproduction project

The following is a very minimal project consisting of a label with around 100k characters.

laggy_text_mrp.zip

AThousandShips commented 1 year ago

For the general slowness of labels this is a duplicate of:

The PR doesn't contain any example of the behavior in a ScrollContainer so that part cannot be tested with this, please update your MRP to display that, otherwise this is a duplicate of that

EchoingLogos commented 1 year ago

For the general slowness of labels this is a duplicate of:

* [Labels with lots of text very slow in Godot 4 #77268](https://github.com/godotengine/godot/issues/77268)

The PR doesn't contain any example of the behavior in a ScrollContainer so that part cannot be tested with this, please update your MRP to display that, otherwise this is a duplicate of that

I came across this while searching. The above issue has a somewhat misleading title: that issue refers to the label loading being slow, not its processing, and the discussion in the issue is about how to solve the loading problem, with no discussion about the processing. Because of this I decided to report the slow processing as a bug, the use case with the ScrollContainer being just an example.

AThousandShips commented 1 year ago

What do you mean by processing? How is this displayed in the MRP? The MRP just contains the loading, no processing is done.

The other issue isn't about loading, but about shaping the text

EchoingLogos commented 1 year ago

What do you mean by processing? How is this displayed in the MRP? The MRP just contains the loading, no processing is done.

Check step 3 in the reproduction steps. In my 12700k system, the profiler reports a process time of around 20ms for the main scene. This means that the frame-by-frame processing of the Label is slow, and not just the initial processing that the above issue is describing. For example, the method given by the author of the above issue does not help reduce the process time.

image

(The loading issue exists in this MRP, but it's ultimately not the problem I'm reporting.)

AThousandShips commented 1 year ago

Does this persist beyond the initial loading? It looks like it stabilises

EchoingLogos commented 1 year ago

Does this persist beyond the initial loading? It looks like it stabilises

Here's an example with the same process as the above image ran for ~8000 frames. It looks like the process time remains very slow throughout.

image

AThousandShips commented 1 year ago

Can confirm that it is high, though I don't see any spikes at all

clayjohn commented 1 year ago

This might be a rendering issue. "Process time" includes the time to render the frame.

Please try testing using the compatibility renderer and see if it helps stabalize / reduce frame times

On my device the frame time drops from 25 ms to 3 ms when switching renderers

EchoingLogos commented 1 year ago

This might be a rendering issue. "Process time" includes the time to render the frame.

Please try testing using the compatibility renderer and see if it helps stabalize / reduce frame times

On my device the frame time drops from 25 ms to 3 ms when switching renderers

Switching to the Compatibility renderer does significantly reduce both the average process time and the variance:

godot windows editor x86_64_atBNUfw758

Unfortunately this is still a tad too slow for production, especially given that other use cases for large-text labels (e.g. loading an entire 4 MB book the user can scroll through) would be much larger.

For example, in my current project, FPS tanks to 7 when the player opens one of the books. This could be solved by breaking up the book into pages or chapters; but even just a single chapter tanks the FPS, and I have features that allow the player to interact with the book such as bookmarking or highlighting which would be much less usable in a paginated format.

(After writing the above paragraph, I had an idea and I'm happy to share a workaround)

While Label is laggy, the TextEdit and RichTextLabel nodes are not, and are able to handle millions of characters without issue.

The bug still stands with respect to Labels, but given this workaround it seems that it's not very urgent.

Maran23 commented 1 year ago

While Label is laggy, the TextEdit and RichTextLabel nodes are not, and are able to handle millions of characters without issue.

The bug still stands with respect to Labels, but given this workaround it seems that it's not very urgent.

@Calinou also reported this behaviour in https://github.com/godotengine/godot/pull/79599

bruvzg commented 1 year ago

A common use case for a Label in some applications is to encapsulate it within a ScrollContainer, allowing the user to scroll through the entirety of the text.

This is not an intended use case for the Label, it doesn't have a built-in scroll bar for a reason. If you want a lot of text, use RTL.

There are multiple parts to the issue: