手游內存佔用過高?如何快速定位手游內存問題

針對手游的性能優化,騰訊WeTest平台的Cube工具提供了基本所有相關指標的檢測,為手游進行最高效和準確的測試服務,不斷改善玩家的體驗。目前功能還在免費開放中。點擊鏈接Unity性能分析立即體驗!

作者:Oliver,騰訊WeTest團隊產品經理。商業轉載請聯繫騰訊WeTest獲得授權,非商業轉載請註明出處。

WeTest導讀

為了避免手機性能成為遊戲選擇時的壁壘,遊戲廠商必須進行更好的遊戲性能優化。本文利用WeTest平台的Cube工具,通過三步完成遊戲內存檢測與分析的過程,希望為遊戲開發者提供一些內存優化的方法和思路。眾所周知,手游在2016年進入了成熟期,全球的開發商數量在減少,遊戲增速也在放緩,更少的遊戲意味著高質量的遊戲將獲得更多的傳播和更久的生命力,質量的提升就會帶來畫面的美化、場景的豐富等,對手機性能也帶來了更多的考驗。為了避免手機性能成為遊戲選擇時的壁壘,遊戲廠商必須進行更好的遊戲性能優化。那麼,遊戲性能是什麼?遊戲性能就是決定了遊戲耐久度,承載能力運行速度的因素。

簡單來說,遊戲性能決定了你的遊戲能否跑的更穩跑的更久跑的更快。進入了手游精品時代之後,為什麼不管什麼遊戲,言必談手游性能?因為在PC時代,如果遊戲性能優化一般,玩家加個內存換個CPU或者刷個主頻就能輕鬆搞定;到了手游時代後情況則顯得比較嚴峻,捉襟見肘的內存使得資源載入時如履薄冰,加上高中低不同配置的機型讓性能問題顯得更加突出,對於玩家來說,為了一款遊戲而更換手機的可能並不大,一個低端機型上的卡頓就可能造成一大批用戶的流失,如果手游性能表現糟糕,再好的遊戲設計都會付諸東流。

那麼什麼樣的手游才是更穩,更久,更快的呢?

我們一般看這樣幾個指標:

對於手游來說,這些指標的情況就決定了遊戲的實際表現,如果光看這些指標沒有直觀的感受,可以看下圖:

如果說左邊是玩家經常會遭遇到的表面現象,那右邊則是基於手游性能深挖後的問題本質。

為了讓遊戲的優化能夠更加系統,更加有的放矢,騰訊WeTest將監控手游性能相關的每個指標,並根據測試的結果進行優化。

那麼,先來說說手游性能的重頭,內存指標的檢測。為什麼是重頭呢?內存的佔用過高通常會帶來「遊戲閃退」、「卡頓」、「系統重啟」等現象,其中每一個結果基本都對遊戲的體驗是致命的。之前騰訊WeTest公眾號先後發布了兩篇關於Unity遊戲內存管理的文章:《內存是手游的硬傷——Unity遊戲Mono內存管理與泄漏》和《深入淺出再談Unity內存泄漏》,詳細介紹了Unity遊戲中內存泄漏會導致的後果以及一些解決的辦法,這次我們將繼續從騰訊WeTest平台的Cube工具出發,通過簡單的三步,介紹如何通過內存的檢測,發現內存管理的問題,優化手游的性能。

第一步:測試遊戲apk

首先要注意:手機必須root

1、安裝WeTest助手登錄WeTest騰訊質量開放平台,在「產品「菜單下選擇」性能測試「,點擊」Unity客戶端性能測試「

或者直接登錄Unity內核性能分析,點擊「Android版 下載」,也在頁面末尾掃描二維碼直接下載。

2、登錄

安裝好客戶端後點擊WeTest助手啟動,選擇一種賬號登錄方式登錄。

3、測試

測試類型選擇「Cube」。

①首先確認「手機狀態」為」手機已Root「;

②點擊「應用選擇」選擇需要測試的應用(選擇Unity遊戲) ,非Unity遊戲可以點擊「通用性能檢測」

③選擇測試類型,測試類型分為四類:Unity性能測試(標準)、Unity性能測試(重度)、Unity資源測試、Mono內存檢測。

那麼這時候,問題就來了,一般應該先開始進行哪項測試呢?

選項一:Unity性能測試(標準)首先我們看第一個,Unity性能測試(標準),該測試主要滿足Unity引擎遊戲日常性能審核的測試需求,覆蓋FPS、CPU、PSS、Mono內存峰值四個維度;建議使用該測試獲取準確性能數據,了解遊戲的一個整體的性能表現,如果測試結果良好,說明遊戲目前的性能表現已經非常好了,可以不需要進行很大程度的優化;如果測試結果不好,則可以考慮進行其他的測試模塊。 選項二:Unity性能測試(重度)

該測試在性能測試(標準)的基礎上,增加了函數耗時統計、單個FPS點中各幀的幀時間、Drawcall數量及每個函數具體出現的位置;建議使用該測試定位性能問題,為之後的性能優化做準備。

選項三:Unity資源測試

該測試可以獲取遊戲過程中多種資源數據,包括資源重複率、GameObject數量 、2D紋理大小 、網格大小 、動畫剪輯大小 、音頻大小 、關卡間保留資源 、Material對象拷貝數量等。建議在對內存優化進入到了資源階段的時候,可以進行這個測試。

選項四:Mono內存檢測該測試提供了獲取快照點的Mono內存對象情況(對象類型、對象大小、對象堆棧、對象引用關係 等);建議在定位存在問題的內存時,可以進行這個測試。

④確定測試類型之後,點擊「開始測試」

A.Unity性能測試(標準)、Unity性能測試(重度)、Unity資源測試中都可以通過點擊「開始記錄」、「結束記錄」來記錄核心場景的性能數據、資源數據。

B.Mono內存檢測中通過點擊「mono內存快照」獲取當前mono內存的詳細情況,單次測試中可以任意在需要快照點的位置設置快照。

⑤「上傳」,退出遊戲,選擇測試遊戲的遊戲類型(最多選擇兩類),點擊「確定」,在彈出的上傳頁,點擊「上傳」,完成數據的上傳。

4.日誌

日誌主要是記錄歷史測試數據,顯示歷史測試中數據是否上傳的狀態,綠色為「已上傳」,紅色為「未上傳」。

通過點擊「清空歷史記錄」可以清除客戶端的日誌中記錄的歷史數據。

第二步:查看報告中的內存情況

點擊「我的主頁」

測試類型選擇「Cube

找到測試報告,點擊「查看」

第三步:分析報告

如果要對手游內存管理進行優化,首先要明確一個分析的策略,Cube團隊的建議是看四塊內容:

  1. 了解手游內存整體表現

  2. 通過mono內存查看是否發生內存泄漏

  3. 通過mono快照定位存在問題的內存

  4. 通過內存分配總表定位存在問題的函數

1、了解手游內存整體表現要觀察手游內存的整體表現,首先觀察遊戲的堆內存峰值是否超過了建議值,如下圖:

其中,建議值的來源是根據騰訊內部的性能標準,對手機的配置等級而形成的內存閾值,圖中的高配機型,PSS內存峰值到達450MB或者mono內存到達50MB的時候就會開始預警。

如果需要更加詳細的指標情況,可以選擇「性能報告」部分中的「mono內存」:

如下圖,我們可以看到內存峰值的超標線,如果超過,那麼那一刻你的遊戲極有可能出現上述「閃退」,「卡頓」和「系統重啟」的現象了;如果沒有超過,那麼恭喜你,繼續進入下一個關卡,檢查你的遊戲是否存在內存泄漏的現象。

2、通過mono內存查看是否發生內存泄漏

對於目前絕大多數基於Unity引擎開發的項目而言,其託管堆內存是由Mono分配和管理的。「託管」 的本意是Mono可以自動地改變堆的大小來適應你所需要的內存,並且適時地調用垃圾回收(Garbage Collection)操作來釋放已經不需要的內存,從而降低開發人員在代碼內存管理方面的門檻。

那麼我們所說的內存泄漏情況,就是遊戲在調用了一些資源結束之後(比如MOBA遊戲中的5V5副本),沒有及時的釋放這些內存,從而導致堆內存的大小越來越多,從而超過了手機內存的閾值。

在比較合理的內存策略下,mono內存應該上升到一定階段之後便不再變化,如下圖:

如果內存產生了泄漏,便有可能出現下圖的情況,堆內存的數值階段性的不斷提升。

如果你的遊戲堆內存出現了不斷上升的情況,需要排查一些內存泄漏的原因,可以進入下一個階段,檢查具體場景中內存的分配情況。

3、通過mono快照定位存在問題的內存

對於mono內存泄漏,一般只能通過猜測+不斷修改代碼測試的方法來修復問題,效率很低,騰訊WeTest平台的Cube工具提供了mono內存快照對比的功能,並包括對象分配堆棧,對象引用關係等詳細信息,是定位mono內存泄漏問題的一大利器。在具體操作中,需要我們進行一次「mono內存檢測「,具體操作可見上文」第一步「和」第二步「。

在「mono內存檢測「的測試報告中,我們可以發現測試報告對每個場景都進行了標記,形成了一個」snapshot(快照)「,對比兩次snapshot,查看兩者之間的新增對象:

這些不同的snapshot內存使用情況的波動意味著遊戲在進行遊戲內存分配和釋放,通過對這些snapshot進行對比,可以發現哪些內存新增了,哪些內存保留了,從而找到遊戲在內存分配上產生的問題,那麼如何進行操作呢?

如上圖所示,在「mono內存檢測「的測試報告中,每兩個snapshot都可以進行對比,通過滑鼠單擊就可以選擇,選中兩個場景之後就可以點擊」提交對比「:

點擊之後會得到兩個場景之間的內存分配比較,其中」對象堆棧「就代表遊戲中實現的一個對象,以MOBA遊戲為例,上圖中的snapshot1和snapshot2所對應的兩個場景可能就是「5V5戰鬥副本「和」遊戲大廳「,通過右上角的」快照間新增top50「和」快照間保留top50「,我們可以了解到這兩個不同的場景之間,哪些對象的資源被保留了,哪些對象的資源新增了(如果需要更多數據,可以點擊右上角的」下載對比報表「),而這些行為是否是遊戲程序所需要的。

可以看到,按鈕按下前後新增的最大對象即為代碼中生成的Byte對象,並且該對象被引用的次數為1。

那麼,如何在遊戲運行中看待這種快照之間新增或保留堆棧的現象?

比如說,王者榮耀這類MOBA遊戲在副本和遊戲大廳之間,會保留地圖和NPC的對象資源,保證下次開始遊戲時可以更快的讀取和進入遊戲;而天天酷跑之類的跑酷遊戲在在副本和遊戲大廳之間,就不會保留地圖和NPC的對象資源,原因就在於王者榮耀這類的MOBA遊戲,地圖和NPC的出現的情況是完全相同的,為了更好的遊戲體驗,保留對象資源是合適的;而天天酷跑之類的跑酷遊戲,有不同的關卡副本,如果保留對象資源,會導致內存不斷的被佔用,因此選擇不保留對象資源。因此我們可以說,內存分配是否合理沒有絕對意義上的標準,都要遊戲開發者根據自己的開發策略,結合mono內存檢測的報告,判定內存分配的情況是否在自己的計劃之中。

4、通過內存分配總表定位存在問題的函數

重新刷新一下報告,我們最後來看一下遊戲整體運行過程中具體功能的內存分配的情況:

圖中的」分配堆棧「代表的就是遊戲每次調用的一個函數,開發人員需要關注右上角」分配總次數「和」分配總大小「,關注是否有函數頻繁分配內存,根據計劃中的內存分配和實際的內存分配情況,開發人員應該進行針對性的優化。

測試報告分析到這裡,基本可以發現內存管理方面存在的一些分配方面的問題了,但是內存優化的道路,到這裡才完成了一半,Unity遊戲在運行時的內存佔用情況可以用下圖表示:

Mono內存和native內存是PSS內存主要的組成部分,mono內存更多的起到內存調用的功能,因此常常成為了開發人員優化內存的起點;而native內存中包含了大量對象的資源,也是內存優化中的重要部分,這部分內容在測試報告中也有具體的細分,如下圖:

這部分的內存檢測,將在後面的乾貨中繼續介紹。

針對手游的性能優化,騰訊WeTest平台的Cube工具提供了基本所有相關指標的檢測,為手游進行最高效和準確的測試服務,不斷改善玩家的體驗。目前功能還在免費開放中。點擊鏈接:Unity性能分析立即體驗!


推薦閱讀:

從零開始學基於ARKit的Unity3d遊戲開發系列2
Unity3D熱更新LuaFramework入門實戰(3)——編寫Lua邏輯
【Unity】工具類系列教程——對象池!
報名 | UWA優化日廈門站

TAG:Unity游戏引擎 | 手机游戏 | 性能优化 |