Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Don't miss out on the Unite LA Keynote for the latest information from Unity! Set a reminder!
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

TextMesh Pro Runtime allocation and huge CPU usage

Discussion in 'Unity UI & TextMesh Pro' started by enigmagame, Oct 3, 2018.

  1. enigmagame

    enigmagame

    Joined:
    Feb 16, 2014
    Posts:
    8
    I've an object that contains a TextMeshProUGUI component, imagine that this object is used as a balloon in a dialog sequence so, based on the user input, the text inside this balloon change throught the dialog progress.
    I manually set the text at each interaction with the method SetText and then I manually call the method ForceMeshUpdate.
    The only other propery of the component that I use is preferredHeight.
    So, in sequence, I manually call SetText, ForceMeshUpdate and preferredHeight.
    I don't know why, and I think that it's not normal, but each of the previous call cause a memory allocation and a huge CPU usage (obviously for one frame).
    For me nor the runtime memory allocation nor the huge CPU usage are acceptable, but at the moment I can't figure out a way to tackle down the issue and to check where the issue is.
    Anyone can help me or give me some suggestion?

    Thanks,

    P.S.: I'm using the version 1.2.2 under Unity 2017.4.10f1.
     
  2. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    1,739
    The SetText() function (not the StringBuilder variant) is used to concatenate a string with a variable without generating allocations. So unless you are combining a string with some value, you should be using the "TMP_Text.text" property.

    It is also important to note that SetText() in the editor does result in allocations to keep the editor text input box in sync with the provided text. This allocation does not occur at runtime.

    In terms of CPU usage, how much text are we talking about?

    Are you using Auto-size on the text?
     
  3. enigmagame

    enigmagame

    Joined:
    Feb 16, 2014
    Posts:
    8
    Just more details: I'm profiling a standalone build (Development Build), so the editor overhead is not present, and I'm not using the Auto-size on the text.
    I'm not combining any text, so the use of the SetText() function is my fault, I've just switched to "TMP_Text.text" property, I've profiled and can see that the allocation in TMP_Text.set_text() is gone.
    But the other allocations and CPU usage remains, I'll try to give you more details.

    Setting the string 123456789 causes an allocation in TextMeshProUGUI.ForceMeshUpdated() (that I call manually after text set) of 9.5KB and a CPU work of 7.17ms. The other property that I manaully call is preferredHeight, and this call causes an allocation in TMP_Text.GetPreferredHeight() of 5.1KB and a CPU work of 6.28ms.
    So calling this two functions causes a runtime memory allocation and a huge CPU work.

    Now, after the user input, I set (on the same object) the string 123456789123456789, this causes in TextMeshProUGUI.ForceMeshUpdated() an allocation of 18.5KB and in TMP_Text.GetPreferredHeight() an allocation of 9.9KB, this time the CPU load is absolutley normal.

    After another user input, I set (on the same object) the string 123456789123456789123456789, this time there are any allocation nor strange CPU usage.

    Just another user input, I set (on the same object) the string 123456789123456789123456789123456789, this causes in TextMeshProUGUI.ForceMeshUpdated() an allocation of 36.7KB and in TMP_Text.GetPreferredHeight() an allocation of 19.8KB, this time the CPU load is absolutley normal.

    Using the -deepprofiling option I can give you more details about the allocation stack, I've attached two screenshot (taken after setting the last string).

    Can you help me to tackle down this issue? Can I do some specific test in order to give you more info?
    Thanks.
     

    Attached Files:

  4. enigmagame

    enigmagame

    Joined:
    Feb 16, 2014
    Posts:
    8
    Anyone can help me or give me some more insights?
    Thanks.
     
  5. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    1,739
    When a text object is first created some initial arrays / buffers are allocated. Assuming the number of characters of the text do not cross a certain threshold, there should be no additional allocations. However, should the number of characters increase then additional allocations will be necessary. These allocations are done in blocks.

    Are you using Layout Components on these text objects?

    After calling ForceMeshUpdate(), you should be able to simply check the .preferredHeight instead of calling the GetPreferredHeight() function which causes a re-layout of the text.
     
  6. enigmagame

    enigmagame

    Joined:
    Feb 16, 2014
    Posts:
    8
    And it's clear obviously. There is a way to pre-allocate these arrays/buffers in order to avoid runtime allocations? Or it's not possible?

    No, in the game object where the text is and also in parents no Layout Components are used.

    I'm already using .preferredHeight, what you see in my precedent post (TMP_Text.GetPreferredHeight()) is what I see from a deep profile session (of the standalone build), that causes an allocation each time.
    But I can tall you that the sizeDelta of the RectTransform father of the text object, is modified before .preferredHeight is called,
     
    Last edited: Oct 10, 2018