uGUI’s text in the same use case seems to reuse the memory instead of allocating and discarding it constantly. Notice the first four spikes in GC allocations, which then subside.
Can you provide more insight on your testing setup?
Are you testing allocations when the text object is first instantiated or when updating the text at runtime?
How are you setting the text? Are you using the .text property or the SetText() function?
Once I have more information and answers to the above, I can provide more insight.
Note: Other than the initial allocations, there should be no other allocations at runtime unless the text content keep growing thus requiring increasing the internal array used in the parsing and layout of the text which are allocated in blocks.
In the above profiler samples, what is the text being set?
How are you testing this?
I am trying to understand how you are setting the text as this could impact / result in allocations.
For instance, internal buffers are allocated in blocks to minimize the frequency of potential allocations as the text grows in size. However, in order to minimize the potential of ending up with geometry allocations that greatly exceed the amount of text which can happen when you go from a text object that contains 10 characters to 1000 then back to 10, TMP will re-size these internal buffers as the geometry is now too excessive relative to the text.
How does the above example impact how you set the text? Some users often set the text to some value and then set it back to string.empty shortly thereafter. When doing so, it can trigger a re-sizing of these internal buffers and result in new allocations.
So all my questions are related to getting a clear understanding of how you are testing this as provided the text remains roughly the same size, there should not be any allocations at runtime other than the initial allocations.
Indeed, the text being set vary in size, sometimes from 10-20 to hundreds of characters. Particularly, it’s a visual novel type of game, where the text box occupy nearly the entire screen and can contain any number of characters. It’s fine when playing normally, but there’s a “skip” mode, where player is able to fast-forward the story making the text change very constantly and that’s when those GC allocations become the bottleneck. Is there a way to prevent allocations in such usage scenario, similar to how uGUI handles it?
Can you submit a bug report with project or with some scene that would enable me to take a closer look at how you are handling all of this?
Most likely the issue is the result of going from lots of text to little text where the resizing to handle excessive geometry is causing the issue. If I was to disable to re-sizing, the allocations would go away but before doing so, I want to verify with your project or some scene that does the same thing to make sure everything works as expected.
As I suspected the behavior is simply related to the internal buffers allocations where in order to avoid potential excessive allocations they are resized. Since in your case, the text content can vary in size by more than several 100 characters from one update to the other, it triggers this resizing.
To disable this behavior, please make the following change which will be included in the next release of the TMP package. With this change, internal buffers will continue to grow to accommodate growing amount of text but will no longer be reduced in size.
In the TMPro_UGUI_Private.cs file, make the following changes.
Then in your own script, set the following property to false to disable this dynamic resizing of internal buffers when the text shrinks.
/// <summary>
/// Determines if the data structures allocated to contain the geometry of the text object will be reduced in size if the number of characters required to display the text is reduced by more than 256 characters.
/// This reduction has the benefit of reducing the amount of vertex data being submitted to the graphic device but results in GC when it occurs.
/// </summary>
public bool vertexBufferAutoSizeReduction