1. 程式人生 > 其它 >子執行緒GC導致主執行緒函式耗時較高的問題

子執行緒GC導致主執行緒函式耗時較高的問題

1)子執行緒GC導致主執行緒函式耗時較高的問題
​2)升級Unity大版本後,Text顏色修改問題
3)清除增量式GC導致的Mono堆記憶體洩漏問題
4)多Pass合批優化問題


這是第274篇UWA技術知識分享的推送。今天我們繼續為大家精選了若干和開發、優化相關的問題,建議閱讀時間10分鐘,認真讀完必有收穫。

UWA 問答社群:answer.uwa4d.com
UWA QQ群2:793972859(原群已滿員)

Rendering

Q:在主執行緒中有非常多的卡頓,從UWA的報告中看到很多異常的高耗時,請問可能是什麼原因造成的?

A:像上面這樣的頻繁卡頓,且卡頓函式種類非常多的情況,應該是子執行緒分配了非常多的堆記憶體,導致子執行緒GC,從而卡住了主執行緒。當GC的時候,主執行緒可能會處於各種階段,因此對應階段的函式耗時就會包括等待GC的耗時。可以從UWA的Mono報告中檢視是否有子執行緒分配了大量的堆記憶體,通常是由這種(Thread)打頭的子執行緒函式的分配導致的。

感謝han@UWA問答社群提供了回答


UGUI

Q:從Unity 4.6.9f1升級到Unity 2020.3.2.f1c1。首次Unity升級之後UI的Text顏色修改是正常。當執行一次之後,所有的Text顏色都無法修改了。就算新建立一個新的Text也無法修改。

A:會有多餘的UI-Default和UI-DefaultFont這兩個Shader,刪除它們,然後重啟Unity就好了。

感謝芝麻青豆角@UWA問答社群提供了回答


Mono

Q:最近在研究Mono堆記憶體時,發現一幀內分配多次較大記憶體,會導致記憶體無法被回收。

過程如下:

在同一幀內呼叫三次分配100MB記憶體的方法,分配記憶體的變數都是在各自的作用域,在這之後呼叫GC.Collect()。發現有較大機率出現100MB或者200MB無法被回收的Mono堆記憶體。經過排查之後發現取消勾選Incremental GC之後,記憶體就能完全被收回。

我推測是每次申請記憶體的時候會執行一次GC,清除上一次分配的記憶體,但是由於使用增量GC,無法在本幀完成回收工作。再下一次GC的時候,第二次GC的回收內容被重置了,導致第二次的GC需要被回收的記憶體就洩漏了。

不知道我這麼理解是不是對的,希望大佬們解惑。同時希望大佬告知有沒有辦法清除這部分記憶體。

測試環境:
Unity 2019.4.15c1
Unity 2020.4.15f2

測試平臺:
安卓 Mono

以下為測試程式碼:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;

public class TestMonoMemory : MonoBehaviour
{
    void Do()
    {
        CallBack01();
        CallBack02();
        CallBack03();
    }

    public void CallBack01()
    {
        List<int> i = new List<int>(1024 * 1024 * 100 / 4);
        //CallBack02();
    }

    public void CallBack02()
    {
        List<int> i = new List<int>(1024 * 1024 * 100 / 4);
        //CallBack03();
    }

    public void CallBack03()
    {
        List<int> i = new List<int>(1024 * 1024 * 100 / 4);
    }

    public string text;

    private void OnGUI()
    {
        GUILayout.Label("Allocated Mono heap size :" + Profiler.GetMonoHeapSizeLong() / (1024 * 1024) + "MB");
        GUILayout.Label("Mono used size :" + Profiler.GetMonoUsedSizeLong() / (1024 * 1024) + "MB");

        GUILayout.Label("Total Reserved memory by Unity: " + Profiler.GetTotalReservedMemoryLong() / (1024 * 1024) + "MB");
        GUILayout.Label("- Allocated memory by Unity: " + Profiler.GetTotalAllocatedMemoryLong() / (1024 * 1024) + "MB");
        GUILayout.Label("- Reserved but not allocated: " + Profiler.GetTotalUnusedReservedMemoryLong() / (1024 * 1024) + "MB");

        if (GUILayout.Button("DO"))
        {
            Do();
        }

        if (GUILayout.Button("DO1"))
        {
            CallBack01();
        }

        if (GUILayout.Button("DO2"))
        {
            CallBack02();
        }

        if (GUILayout.Button("DO3"))
        {
            CallBack03();
        }

        if (GUILayout.Button("GC"))
        {
            System.GC.Collect();
        }
    }
}

  

A:通過題主的方法,我也復現了該問題。我還是比較贊同你的理解的。

Unity官網的一篇關於增量GC的部落格也寫了該方法的弊端:

它的正常執行是需要前提的,那就是在GC期間這些被標記為“需要清理的記憶體”都保持不變。如果在GC期間變化了,比如頻繁分配大量記憶體,那麼就需要重新標記一遍,而這個階段可能會有意想不到的bug產生。記憶體洩漏很可能就是發生在這個階段(我也只是猜測)。

不過個人覺得增量GC仍然是一個良好的嘗試,雖然它只是測試階段,也存在著一些問題,但是以前的Boehm-Demers-Weiser garbage collector很容易引起高耗時峰值從而造成卡頓,而分代式GC正是為了減輕峰值的影響,儘量確保流暢性。

可以參考官方部落格:https://blog.unity.com/technology/feature-preview-incremental-garbage-collection

該回答由UWA提供


Rendering

Q:遊戲使用簡單的Mesh顯示幾十張撲克牌,為了效果,材質Shader使用了2個Pass,其中一個是拉伸做邊緣效果,但是由於是多Pass,即使是相同的材質和貼圖,還是不能動態合批,請教這種情況有沒有什麼優化方案?

1. 不能合批,但是材質是相同的,順序渲染過程中是否有什麼狀態切換的消耗?

2. 能否使用兩個Mesh,不同的材質,Shader都使用單Pass,區別是一個Mesh是正常顯示,一個Mesh僅僅做拉伸邊緣效果,理論上是不是不超過頂點數的情況下可以兩次動態合批?

A1:Unity BuiltIn渲染管線不支援多Pass合批,多Pass的Shader通過Set Pass call逐個渲染每個Pass後才會繼續渲染下一個Object重複一遍,所以會產生比較多的Draw Call。

更好的辦法就是用自定義的渲染管線的方式渲染多個Pass。在渲染第一個Pass的時候,把所有的Object一次性全都渲染了,渲染完畢之後通過一次Set Pass Call去渲染下個Pass,可以試下URP渲染管線。

感謝星傲蝶戀@UWA問答社群提供了回答

A2:題主說的第二點是比較常規的做法,要注意的是為了防止Draw Call的穿插,需要調整這兩種渲染的RenderQueue,將他們對應的RenderQueue錯開。

感謝Xuan@UWA問答社群提供了回答

20211108
更多精彩問題等你回答~

  1. Unity增量打包AssetBundle沒變化的資源也會被重新打包
  2. 在模型有UV2的情況下開啟Generate Lightmap UVs
  3. 如何實現AAB包的增量更新

封面圖來源於網路


今天的分享就到這裡。當然,生有涯而知無涯。在漫漫的開發週期中,您看到的這些問題也許都只是冰山一角,我們早已在UWA問答網站上準備了更多的技術話題等你一起來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官網:www.uwa4d.com
官方技術部落格:blog.uwa4d.com
官方問答社群:answer.uwa4d.com
UWA學堂:edu.uwa4d.com
官方技術QQ群:793972859(原群已滿員)