0x00 問題
不知道大家是否在調試Unity應用性能的時候發現過一條常見的Marker:UIEvents.IMGUIRenderOverlays。
很多情況下,這條叫做UIEvents.IMGUIRenderOverlays的Marker下會有持續的GC內存分配以及CPU時間的開銷。如下圖所示:
可以看到在這個截圖中,UIEvents.IMGUIRenderOverlays的GC分配為368B,時間開銷為0.27ms,並且是每幀持續如此的輸出。
0x01 原因
一旦發現UIEvents.IMGUIRenderOverlays中花費了大量的主線程CPU時間以及GC分配,這就表明在項目的代碼庫中的某處使用了Unity的即時模式GUI系統:即便是在代碼庫中僅出現一次OnGUI方法,也會導致IMGUI系統在游戲運行時進行初始化和處理。
重要的是IMGUI非常低效,不適合生產代碼。
void OnGUI() { if(GUI.Button(new Rect(100, 100, 100, 100), "Load UI")) { //TODO } }
檢查一下我們的項目,果然在一個測試腳本中發現了一個OnGUI方法的實現。Ok,現在我們把OnGUI方法注釋掉再來看一看Unity Profiler提供的數據。
可以發現,去掉了OnGUI方法之后,UIEvents.IMGUIRenderOverlays的開銷從之前的每幀GC分配368B降到了0B,CPU的時間開銷從0.27ms降到了0.01ms。
如果點開UIEvents.IMGUIRenderOverlays的內容,可以看到一個叫做GUI.Repaint的Marker,這個Marker所對應的Unity的底層方法會收集所有實現了OnGUI方法的腳本,對這個OnGUI方法的實現進行繪制。
可以看到,針對OnGUI的使用不僅僅不易於維護代碼的可讀性,甚至是可能會引起不必要的開銷,哪怕只有一個OnGUI的實現不小心隨發布版本一同發布都會帶來這種開銷。
因此一個小建議是,大家可以在項目的代碼庫中搜索OnGUI方法並手動刪除它們,或通過使用合適的#if預處理語句將它們包起來,以確保將它們從發布構建中移除。
https://docs.microsoft.com/zh-cn/learn/?WT.mc_id=DT-MVP-5001664