Android顯存profile方法、mali芯片顯存占用高的問題

獲取顯存值

??安卓上debug顯存,除了游戲引擎自帶的profiler外,還有更底層的統(tǒng)計方式,用adb獲取內(nèi)存大小,命令為:

adb shell dumpsys meminfo <應(yīng)用包名>

??這可以獲取到類似下列的列表:

Applications Memory Usage (in Kilobytes):
Uptime: 1307163772 Realtime: 1442234389

** MEMINFO in pid 26060 [games.guanyou.ca.ymr] **
                   Pss  Private  Private  SwapPss      Rss     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty    Total     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------   ------
  Native Heap    30104    30024       12      105    30888    48356    45145     3212
  Dalvik Heap     1815     1676       36       74     2616    11550     2887     8663
 Dalvik Other     1668     1556       56        0     2172
        Stack     1892     1892        0        0     1900
       Ashmem      136        0        0        0     1020
      Gfx dev      392      392        0        0      396
    Other dev       19        4        8        0      544
     .so mmap    77560    11596    61188        8   111328
    .jar mmap     4411        0     2012        0    44044
    .apk mmap      441        0       12        0     1812
    .ttf mmap     2213        0      384        0     5584
    .dex mmap     7177       52     7072        0     7936
    .oat mmap       31        0        0        0     2004
    .art mmap     7700     5656     1060       43    16472
   Other mmap    10389        8    10220        0    11420
   EGL mtrack    37000    37000        0        0    37000
    GL mtrack      764      764        0        0      764
      Unknown    16209    16068       92        1    16596
        TOTAL   200152   106688    82152      231   294496    59906    48032    11875

 App Summary
                       Pss(KB)                        Rss(KB)
                        ------                         ------
           Java Heap:     8392                          19088
         Native Heap:    30024                          30888
                Code:    82316                         172756
               Stack:     1892                           1900
            Graphics:    38156                          38160
       Private Other:    28060
              System:    11312
             Unknown:                                   31704

           TOTAL PSS:   200152            TOTAL RSS:   294496       TOTAL SWAP PSS:      231

??和圖形相關(guān)的有如下信息:

Gfx dev      392      392        0        0      396
EGL mtrack    37000    37000        0        0    37000
GL mtrack      764      764        0        0      764

Graphics:    38156                          38160

??上述是在adreno芯片的手機(jī)上獲取到的信息,而如果是在mali gpu的手機(jī)獲取,只會獲取到如下信息:

GL mtrack   111392   111392        0        0   111392\

Graphics:   111392                         111392

??觀察上述信息,我們能簡單得到一些結(jié)論: adreno芯片獲取的信息中,Gfx dev + EGL mtrack + GL mtrack的結(jié)果,恰好是Graphics中的值。
??多次在手機(jī)運(yùn)行demo程序中,我發(fā)現(xiàn)多次用adb獲取上述信息時,adreno手機(jī)上,Gfx dev時刻在小范圍波動,每次獲取都不同;EGL mtrack不會輕易發(fā)生變化,GL mtrack和紋理相關(guān),在demo程序中添加紋理,大小會反應(yīng)在GL mtrack中,且紋理的大小幾乎就是GL mtrack的增量(有極小的差異,可能和其他渲染用資源有關(guān))。
??復(fù)制一個特效,再將其刪除,理論上只有shader不會被卸載,其他資源都應(yīng)該被卸載,反應(yīng)在上述結(jié)果中,GL mtrack再復(fù)制前和刪除后幾乎沒有變化,而Gfx dev有很大變化,說明Gfx dev內(nèi)包含Shader Program的內(nèi)存。
??mali芯片只有GL mtrack并和Graphics值相等,懷疑mali芯片獲取的GL mtrack中,包含了Gfx dev + EGL mtrack,不過與時刻變化的adreno芯片Gfx dev不同,mali芯片GL mtrack不會時刻變化,而是當(dāng)demo重新啟動時,每次重啟app,這里值都有微小差異。

發(fā)現(xiàn)的問題與調(diào)查問題

??在mali芯片的gpu中,我們播放的一個粒子特效后,內(nèi)存值顯著高于adreno芯片。
??在Android Studio的Profiler界面(View->Tool Windows->Profiler)可以查看內(nèi)存,其中包含Other、Code、Stack、Graphics、Native、Java等項:



對比上文中的adb命令其中的數(shù)值,可以判定這些值是用同一個方法拿到的(KB轉(zhuǎn)MB需要除以1024):


??用左側(cè)Record native allocation可以記錄堆棧申請的內(nèi)存,并根據(jù)開始與結(jié)束時內(nèi)存的釋放,查看是否有未釋放的內(nèi)存,例如我record灰色部分:

。



??將檢查部分改成Arrange by callstack展開內(nèi)容,用remaining size排序,首先是看起來是有0.5MB的紋理創(chuàng)建導(dǎo)致的內(nèi)存未清理,后面還有g(shù)lBindFramebuffer等申請的內(nèi)存未釋放,這些內(nèi)存是在libGLES.mali.so,也就是芯片廠商提供的動態(tài)庫內(nèi)部申請的。
??合理懷疑可不可能是Unity有些申請的紋理為釋放,因此用高通設(shè)備走同樣的流程對比,發(fā)現(xiàn)高通的remaining size也就不到400KB,并且也沒有紋理相關(guān)的堆棧,說明這與Unity無關(guān),是芯片廠dll內(nèi)部申請的內(nèi)存未釋放。

??將同一特效反復(fù)加載播放然后刪除,mali和adreno設(shè)備的曲線有明顯區(qū)別:



??因此幾乎可以判定,mali芯片的gles動態(tài)庫底層有一個池子。

堆棧內(nèi)存問題

??偶然中發(fā)現(xiàn),在mali設(shè)備上,Graphics峰值增長100MB時,堆棧才顯示分配了不到20MB,而高通設(shè)備上,分配大小顯著高于Graphics峰值,懷疑mali設(shè)備的統(tǒng)計上,至少有一個有問題。
??所以我將11張ASTC4x4紋理(10個2048每個5.3MB,1個1024 1.3MB,合計54.3MB)打為一個Bundle,在運(yùn)行時加載bundle并顯示渲染包含這些紋理的Cube,查看堆棧的增長情況:



??發(fā)現(xiàn)mali設(shè)備的堆棧申請大小才不到20MB,而高通上接近80MB,可以斷定,mali設(shè)備查這里的堆棧是有問題的。
??同時分別查看加載和卸載這50MB紋理的情況,在高通設(shè)備上,加載和卸載紋理時,Graphics幾乎沒有變化,而在adreno設(shè)備上,Graphics比加載紋理前多25MB。

其他情況

??同樣的示例打了Vulkan包試了試,Graphics釋放不全的問題,在mali vk上同樣適用,且對vulkan api的調(diào)度,會調(diào)度到libvulkan.so,然后再調(diào)用到底層的libGLES_mali.so,懷疑mali上vk是封裝了層gl?
??在adreno上測試,實際api調(diào)用是vulkan.adreno.so;結(jié)果50多MB的紋理創(chuàng)建,Graphics才增長32MB,且卸載Bundle銷毀紋理時,Graphics沒有一點(diǎn)下降,不是統(tǒng)計有問題,就是底層有什么機(jī)制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容