就是它,遊戲卡頓的罪魁禍首

在U3D遊戲中內存管理一直都是讓人比較頭疼事情,現在手機遊戲是越做越大,和端遊一樣,每次卡頓和每次的內存增長對玩家來說都是一個比較差的體驗。聽到過一句話,說遊戲開發做久了就會變成“GC怪”,因爲在遊戲開發過程中,需求變化多,功能不停的迭代,內存問題也一直存在,需要不停的去優化它。

在unity2018中集成來正版的.NET4.X和C#7.3,引入了ref return 和ref locals,讓值類型的操作更加便捷,在U3D2019中更是加入來增量式GC,減少來GC帶來的卡頓問題,比以前的版本靈活來許多。

講了這麼多,可能很多人還不知道什麼是GC,GC的全稱是Garbage Collection,也就是垃圾回收的意思,是一種自動管理堆內存的機制,管理堆內存上對象的分配和釋放。

一、內存管理方式

我們常用的內存管理方式有三種:

1.手動管理,像C/C++一樣使用malloc/free或者new/delete來爲對象分配釋放內存。這張方法的優點是速度快,沒有任何額外開銷,缺點是要去人工瞭解每個對象的使用情況,這樣很容易發生各種問題,比如內存泄漏,野指針和空懸指針等。

2.使用引用計數,它的思想是對象創建出來以後,維護一個針對該對象的計數,使用該對象的地方對該計數加1,使用完後減1,當計數爲0時,銷魂該對象。這種方法類似半自動內存管理方式,優點是可以把分配和釋放的開銷分佈在實際使用過程當中,速度比較快,不過會存在一個循環引用的問題。引用計數是一種比較常用的內存管理方法,比如U3D中物理引擎PhysX就是使用引用計數來管理各種對象的。

3.追蹤式GC器,unity使用的GC器是一種叫標記/清除的算法,它的思路是當程序需要進行垃圾回收時,從根出發標記所有可以到達的對象,然後回收沒有標記的對象,這是一種全自動的內存管理方法,程序員完全不用追蹤對象的使用情況,也不存在循環引用無法回收的問題。在unity中使用的是一種叫boehm-Demers-Weiser的GC器,它的特點是:

(1)stop the world ,即當GC發生時,程序的所有線程都必須停止工作,在回收時也要停掉所有線程。

(2)不分代,.NET和java會把託管堆分成多個代,新生代的內存空間非常小,而且一般來說,GC主要集中在新生代上,讓每一次GC的速度很快,但是在U3D中GC是完全不分代的,只要發生GC,就會對整個託管堆進行GC。

(3)不壓縮,不會對堆內存進行碎片整理,類似我們的磁盤一樣,使用久了就會有很多的碎片,造成磁盤上有很多小空隙。同樣在U3D中GC會造成託管堆出現很多這樣的間隙,這些間隙不會合並,當申請一個新對象時,如果沒有任何一個間隙大於這個新對象的大小,堆內存就會增加。

二、影響GC性能的因素

主要因素有2個:

1、可達對象的數量

2、託管堆的大小

可達對象是不會被GC回收的對象,減少這類對象的方法是減少對象的數量,如下:

將會產生10個Actor對象。

如果使用以下方法:

只產生一個對象,方法很簡單,但是卻很有用,如果在需要每幀去處理的對象上去使用這類優化,會得到意想不到的效果。

而優化託管堆的大小主要通過以下幾個方面:

1、減少臨時內存分配,因爲臨時內存會使內存短暫的增長,而且會產生碎片

2、防止內存泄漏,也就是存在互相引用無法回收對象的情況,或者沒用到的對象,但是對它還有引用,導致釋放不掉。

 

歡迎關注公衆號:理想的鍵盤

image.png

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章