2016年5月2日 星期一

淺談Unity Profiler記憶體分析

作者:柳振東 原文

 使用Unity開發遊戲的過程中,借助Profiler來分析記憶體使用狀況是非常重要的。但許多開發者還對Profiler裡各項資料表示含義不甚明確,今天我將針對Profiler記憶體分析相關的問題與大家討論分享。 要想完全發揮Profiler分析的威力,首先要做的就是了解Profiler資料所表達的含義,以及到底哪些模組所使用的記憶體才會被統計到Unity的Profiler中。Profiler涉及到的知識有很多,今天先挑選一些大家常有的疑問來作解答。

Q. 在Unity的Profiler中看到的總記憶體使用和我使用其它工具看到的系統記憶體佔用不太一樣,這是為什麼呢?

Profiler中看到的記憶體是通過Unity引擎的記憶體分配,凡是引擎所分配和釋放的記憶體均會記錄,可以給出明確的引擎記憶體佔用資訊。但仍有其他記憶體資訊我們是無法獲知的。

比如,如果引擎使用了第三方廠商的庫,那麼庫分配的記憶體我們是無法進行統計的。另外,在手機設備上大家看到的記憶體,其實都要比Profiler大很多,這是因為不管是通過Xcode的Instrument還是通過Android的USS,記錄實體記憶體都包括兩部分,一個是使用(Used)的實體記憶體,另一個則是緩存的(Cached)的實體記憶體。




這是系統決定的,Android和iOS系統在資源不使用時當下均不會將它回收,而是放在緩存的實體記憶體中,以便下次再用時,可以快速地載入。當系統發現App的記憶體不夠用時,才會在底層呼叫一個Memory Killer執行緒來檢查緩存,為App清理記憶體。
而Unity Profiler記錄的則是目前真實使用的實體記憶體,即上述所說的第一部分。因此,當遊戲執行時間越長,Profiler分配記憶體和通過其他軟體獲得的系統記憶體差距會越大。
因此,只要所使用的第三方的庫不存在記憶體洩露問題,我們一般都建議只需要查看Profiler即可,只要Profiler中的記憶體可以保證正常讀取和釋放,那就代表引擎分配的記憶體是沒有問題的。

Q. 我們做項目的時候發現有時Profiler中System.ExecutableAndDlls這項佔用很多,有什麼解決辦法嗎?

“System.ExecutableAndDlls”顯示的是執行檔和所呼叫的庫(物理、渲染、IO等系統庫)總和。請不用擔心它的數值,因為很多Application均在共用這些庫,並且它對於真實遊戲的記憶體壓力非常小,而且也不會導致系統因為該記憶體來移除掉遊戲。

Q. 為什麼在Profiler中的Simple模式下,Used Total的數值不等於右邊各項Unity, Mono, GfxDriver, FMOD與Profiler總和呢?

其實在Unity中,Used Total的計算公式為Used Total = Unity + Mono + GfxDriver + Profiler + additionalUsedMemory。公式中的additionalUsedMemory項在Profiler中並沒有顯示,因為這一項一般情況下都為0,只在某些特殊發佈平臺下才會有數值(一般Android,PC和IOS都為0)。因此一般情況下Used Total的值就是除FMOD之外各項的總和了。當然,這個規則對於Reserved Total是同樣適用的。

Q. 我們專案的資源主要使用AssetBundle動態載入資源,發現Profiler中Detailed模式下PersistentManager.Remapper一項佔用時多時少,這一項主要是做什麼的呢?

Remapper主要提供檔的持久化存儲,包括各種序列化的Asset,項目的設置檔等,維護檔案系統的中的檔與記憶體中資料的對應關係。

那麼如果專案大量使用AssetBundle的話,在對AssetBundle Unload之前都會需要佔用Remapper記憶體。而Remapper本身的實現使用記憶體池,數值只會變大,為了使Remapper佔用的記憶體保持在一個穩定的數值上,我們需要每次在載入一定數量的AssetBundle之後進行Unload操作,而不要一次把所有AssetBundle都載入後才呼叫Unload。(這樣的操作對維持整個Mono Heap的大小也是至關重要的,因為Mono Heap本身也是只增不減的。)

Q. 我們在Editor中除錯專案的時候發現貼圖的記憶體大小是其本身大小的兩倍,是因為Unity把記憶體和顯存的大小都計算進去了嗎?


其實並不是這個原因,因為Editor本身會保有貼圖的一份記憶體,在Editor裡Profiler會把Editor本身所使用的紋理大小也計算進去,因此會有記憶體變為兩倍的情況。我們並不建議在Editor下對專案進行效能調試,而是在真的機器上跑編譯好的專案,然後連接Profiler進行除錯,只有這樣才能得到真正精確的測試資料。

總結:一般情況下只需Unity Profiler在手,就能窺測到遊戲中各項記憶體使用狀況,當然前提是需要對Profiler各項資料所表達的含義了然於心。並且儘量使用真的機器結合Profiler除錯,這樣才能瞭解到遊戲執行的真實記憶體佔用資料。

更多相關的內容在Unity官方中文社區(forum.china.unity3d.com),敬請保持關注!

沒有留言:

張貼留言

著作人