使用Mali Graphics Debugger調優Unity程序(Killer示例)

What is MGD

ARM? Mali? Graphics Debugger的作用之一是針對采用ARM? Mali? GPU的Android手機,進行app的GPU運行時調試和調優。

Why MGD

本文MGD主要用于性能調優。

關于GPU性能調優,定性不定量都是耍流氓。
猜是虛的、打嘴炮討論是無用的、運行時正則表達式disable對象是盲目的、Unity Profiler是難于真機調試的、GPA(Intel? Graphics Performance Analyzers)是不同平臺的、Unity FrameDebugger是從實現本質決定了不能定量到高于DrawCall精度的。

另外,本文假設已確定瓶頸出現在GPU。否則,應優先調優CPU性能。直接使用Unity真機調試是不錯的CPU性能調優手段。

Doc & Setup

閱讀[ARM? Mali? Graphics Debugger User Guide](http://malideveloper.arm.com/downloads/tools/mgd/1.3.2/Mali Graphics Debugger v1.3.2 User Guide.pdf)是了解MGD最全面的途徑,里面包括了如何設置MGD和使用MGD。
由于MGD里會直接出現大量OpenGL/OpenGL ES的API,所以也可按需查閱AW OpenGL ES 3.0 Programming Guide 2nd Edition

本文以MGDv2.1版本為基礎進行編寫。編寫完畢后數天(約2015-08-11)得知MGDv3.0已發布,其改進了體驗和UI框架、FrameBuffer View、支持MRT/DepthBuffer/StencilBuffer的截取、更好的截取性能和截取文件大小優化。詳情可參考官網或[Mali Graphics Debugger 3.0.0 User Guide](http://malideveloper.arm.com/downloads/tools/mgd/3.0/Mali Graphics Debugger v3.0.0 User Guide.pdf)。

關于MGD設置,本文為了內容完整性也精簡地描述如下。(你若已設置好或暫不關心設置,也可跳過以下設置步驟,直接閱讀下面的操作步驟、思考過程和發現killer的問題及其以下章節。)

  • 在電腦裝好MGD
  • 準備好Mali GPU的Android手機。基于Mali的設備不少,比如Samsung Galaxy S3等基于Exynos SoC的手機。具體列表見Mali SoC implementation
  • 本文用已Root的Android的設備進行。但未Root也可用,但需要參考上面User Guide,以另外的方式進行。
  • 在電腦上安裝好ADB(Android Debug Bridge),并且把ADB設置到操作系統(windows or OSX)的環境變量中。
  • 連接Android設備和電腦。
  • 打開命令行,輸入:
#拷貝mgd版OpenGL ES運行時庫和mgd后臺進程到手機sdcard文件夾
cd /your_computer/path_of_installed_mgd

adb push libGLES_mgd.so /sdcard/
adb push mgddaemon /sdcard/

#準備進入手機進行命令行操作
adb shell
#以下命令在手機中執行
su
#拷貝mgd版OpenGL ES庫和mgd后臺進程到手機system文件夾并且修改為可執行權限
cd /sdcard/cp mgddaemon /system/bin/mgddaemon
chmod 777 /system/bin/mgddaemon
cp libGLES_mgd.so /system/lib/egl/libGLES_mgd.so
chmod 777 /system/lib/egl/libGLES_mgd.so

#Android 4.2 和 4.3切換到mgd版OpenGL ES運行時庫:改egl.cfg配置方式
cp /system/lib/egl/egl.cfg /system/lib/egl/egl.cfg.bak
echo "0 0 mgd" > /system/lib/egl/egl.cfg

#Android 4.4 and 5.0切換到mgd版OpenGL ES運行時庫:文件鏈接方式
cd /system/lib/egl
ln -s libGLES_mgd.so libGLES.so
ln -s libGLES_mgd.so libEGL_mgd.so
ln -s libGLES_mgd.so libGLESv2_mgd.so
ln -s libGLES_mgd.so libGLESv1_CM_mgd.so

#設置mgddaemon,叫它只調試com.tencent.killer這個進程。這里應填入你自己的進程id
echo "com.tencent.killer" > /system/lib/egl/processlist.cfg

#先退回到電腦,可能不止一次exit
exit

#準備打通調試信息轉發通道
adb forward tcp:5002 tcp:5002

#再次進入手機,啟動mgd后臺進程
adb shell
su
mgddaemon
  • 在電腦上打開MGD,如下圖點擊Connect按鈕


    點擊Connect按鈕,連接MGD和設備
  • 運行killer(或你自己的app)
  • MGD成功自動收集killer的GPU運行時調試信息
MGD成功自動收集killer的GPU運行時調試信息

至此,Setup操作已完畢。接下來,需要保持手機和電腦的USB連接,進行進一步的調試調優操作,亦可用通過菜單將當前調試數據保存到電腦。

操作步驟、思考過程和發現killer的問題

關于killer

killer(產品名字《獨立防線》)為我們項目組一款基于Unity的可FPS/TPS切換、可PVP/PVE的3D射擊游戲。

第一幀:主角第三人稱狀態,未露出FPS狀態精細武器、無特效

在游戲中操作,進入戰斗。并保持主角在主角第三人稱狀態,未露出FPS狀態精細武器、無特效——一個最純粹的戰斗情況。

保持主角在主角第三人稱狀態,未露出FPS狀態精細武器、無特效

從上圖發現MGD已自動收集GPU數據,很是煩人,此時,可點擊暫停按鈕,暫停游戲,從而暫停收集。

點擊Toggle Fragment Count按鈕(注意之前的操作步驟如并非MGD和設備先Connect好了之后才運行app,可能會導致本按鈕無法點擊),再點擊下一幀,可用收集下一幀的Fragment Shader的信息。這是因為Fragment Shader往往是性能消耗大戶,需優先關注。

點擊*Toggle Fragment Count*按鈕,再點擊下一幀

點擊剛剛收集好Fragment Shader信息的第971幀,點擊Fragment Shaders,然后按指令周期比例排序,可立刻知道哪些shader占消耗大頭,比如圖中的第877號shader,名字是“Shader 879”。


雙擊該877號shader,觀察代碼,可知是用于lightmap場景的shader

第877號Fragment Shader程序

所以,可輸出結論一和初步解決方案。

結論一:場景是GPU性能消耗第一大戶,需最優先關注。精簡、優化場景mesh和貼圖、精簡lightmap是可行方法。

再點擊下一個第619號Fragment Shader程序,

第619號Fragment Shader程序

通過經驗可知,為渲染UI的Shader


UGUI的UI-Default.shader

所以,可輸出結論二和初步解決方案。

結論二:UI是GPU性能消耗第二大戶。留意到里面有discard語句,可能帶來性能影響,所以應編寫無clip版本的shader。并且精簡UI、或進行UI紋理打包。

再點擊下一個Shader,發現和UI Shader很相似,只是少了一個顏色的運算,所以也不用有mediump的color_2中間變量。可知是UGUI針對材質顏色為全白色時的優化版Shader

第622號Fragment Shader程序

所以,有結論三。

結論三:UI中,不需用顏色的,應保持此材質顏色為白色。

至此,當前幀的Fragment Shader權重較高者,皆已列出,剩下的Fragment Shader已變得性價比不高。
需轉移目標,比如,Vertex Shader。
同理,切換至Vertex Shader,按cycle排序,找出性能消耗第一大戶,第880號Vertex Shader。通過里面的代碼出現“SH”,可知是球諧函數“Spherical Harmonics”,即用Light Probe進行渲染的主角Shader。

第880號Vertex Shader

所以,有結論四。

結論四:主角頂點數過多(圖中為23469個頂點),是造成性能的瓶頸之一。

同時,留意到我們主角都是距離鏡頭很近的,所以,壓根不需要霧的運算,所以,有結論五。

結論五:主角的Shader,甚至一些在不遠處的敵兵shader,都需要去掉霧運算。

再觀察下一個877號Vertex Shader,留意到是用Light Map進行渲染的場景,所以。


第877號Vertex Shader

同理,亦可以有結論六。

結論六:場景,如有可能,最好也去掉霧運算。

至此,第一幀分析基本完畢

第二幀:FPS狀態,露出精細武器,無槍火特效

游戲戰斗中是個多變的過程,不同時刻的兩個幀顯示的內容可能大相徑庭。
所以需要更換另一種情況進行繼續調優。比如FPS狀態,露出精細武器,無槍火特效。

FPS狀態,露出精細武器,無槍火特效

在之前的暫停狀態下,取消點擊收集Fragment數量按鈕(Get the fragment count statistics),否則將會很卡,然后點擊播放按鈕(Resume Tracing),以和第一幀類似的方法進行數據收集。

取消Get the fragment count statistics,才繼續進行操作

從收集數據看來,結果和第一幀數據并無質變。但由于知道變化的因素是精細武器本身,所以應特定確定該Shader的消耗。
此時,如果對武器Shader不熟悉,可以打開Unity,在Editor重現該情況,在Editor直接閱讀Shader代碼,如下:

精細武器的Shader:Bumped Specular

根據Shader特征ShininessGlossNormalmap等,回到MGD,也是按Cycle數從大到小逐個觀察(因為渲染武器的消耗肯定不會很小),確定為第871號Fragment Shader。

第871號Fragment Shader,用于精細武器的Bumped Specular Fragment Shader

所以有結論七:

結論七:精細武器的Shader的Cycle比例(4.6%)和Shader指令,哪怕是用Surface Shader,也不算復雜,不是瓶頸。這可能是因為Unity的按平臺編譯Shader的優化結果。

第三幀:FPS狀態,露出精細武器,開火,播放開火特效

FPS狀態,露出精細武器,開火,播放開火特效

繼續采集數據。并且點擊開火,觸發開火特效,然后立刻點擊MGD暫停,并進行類似采集。發現有以下新的問題shader。

第862號Fragment Shader占用了10%的cycles

通過觀察Shader代碼,和槍火特效(還有額外的四周防護罩效果)的Shader一致,為

特效Shader,Particles/Additivie

留意到該Shader并不復雜,但卻又霧的處理(理論上可以去掉一個Tint的顏色乘法),并且該特效在Unity觀察overdraw也合理,所以也可以有結論八:

在Unity觀察槍火特效overdraw也算合理

在Unity觀察防護罩特效overdraw也算合理

結論八:槍火特效+滿屏的防護罩特效會導致有額外10%的cycle產生。需去除霧的處理。因為需求原因,占用屏幕面積較大,但Overdraw程度尚算合理。

至此,關于Shader的調優在本文暫告一段落。接下來需要更多實地考察。
另外,操作上還有小技巧,可以通過Frames with features enabled的過濾,剔除沒有詳細數據的幀

可以通過*Frames with features enabled*的過濾,剔除沒有詳細數據的幀

內存情況

內存不會直接影響幀率,但也是性能的一方面表現。過高的內存可能是加載緩慢的誘因、可能會提高app后臺后被系統kill掉的幾率、也可能直接導致內存不足crash。
點擊MGD里的Textures,并點擊Size進行排序。

點擊Textures,并點擊Size進行排序

當前在killer出現了不合理情況有:

不該在戰斗出現的紋理泄露到了戰斗

結論九:主界面的圖標從戰斗外泄露到戰斗內了。需要注意是否戰斗內有錯誤的引用。可使用運行時檢測工具打包Sprite Packer的tag是否戰斗外、戰斗內互斥。亦需要注意資源模塊ResourcesManager是否還有資源引用,導致Resource.UnloadUnused()無法卸載主界面資源。

一個時刻只出現一個的icon圖片可以不打包

結論十:軍銜圖標可能從戰斗外泄露到戰斗內了,也可能是戰斗內就是需要用到。
結論十一:一個時刻很大幾率只出現一個的icon圖片可以不打包,放棄一定的DrawCall效率來換取內存,并且這樣哪怕泄露也可減緩泄露的后果。

尚未提及的更多性能評估點

本文著重從最根本的Shader的Cycles數量進行分析,但尚未提及的更多性能評估點包括:

  • DrawCall是否合理,有否可能合并。Unity 3D游戲中,合并DrawCall會決定于LightMap,也會決定于UI層次間的atlas分布。
  • 是否有過多的OpenGL狀態切換。

更多的優化細節,也可參考ARM? Mali? GPU Version: 3.0 OpenGL ES Application Optimization Guide,或ARM? Guide to Unity Version 2.1 Enhancing Your Mobile Games

MGD(v2.1)尚待改進的地方

MGD(v2.1)尚待改進的地方有:

  • 在本次調優過程中,不能對已Capture的幀進行逐DrawCall重畫(用戶手冊給出了原因);
  • 不能方便觀察頂點模型;
  • 不能以柱形圖直觀地列出時間或Cycles消耗。

上述部分問題已在MGDv3.0得以解決。

About

DonaldW,客戶端開發,現就職于騰訊魔方工作室群。
本文可隨意分發、分享。但請注明署名。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容