內(nèi)存優(yōu)化2

概念理解

4種內(nèi)存類型

1: Unity底層(C++層,本機(jī)堆,核心代碼,unityengine.dll等一系列別稱)占用的內(nèi)存,包含Scene,Audio,CodeSize,貼圖等.Unity使用了自己的一套內(nèi)存管理機(jī)制來使這塊內(nèi)存具有和托管堆類似的功能乱凿×枘牵基本理念是柔滔,如果在這個關(guān)卡里需要某個資源,那么在需要時就加載馍刮,之后在沒有任何引用時進(jìn)行卸載。聽起來很美好也和托管堆一樣潭辈,但是由于Unity有一套自動加載和卸載資源的機(jī)制父泳,讓兩者變得差別很大。自動加載資源可以為開發(fā)者省不少事兒窃判,但是同時也意味著開發(fā)者失去了手動管理所有加載資源的權(quán)力钞楼,這非常容易導(dǎo)致大量的內(nèi)存占用(貼圖什么的你懂的),也是Unity給人留下“吃內(nèi)存”印象的罪魁禍?zhǔn)住?/p>

2: Unity的托管堆(Managed Heap),托管內(nèi)存,也被稱為用戶管理的內(nèi)存,Mono項目一個開源的.net框架的一種實現(xiàn)袄琳,對于Unity開發(fā)询件,其實充當(dāng)了基本類庫的角色。托管堆用來存放類的實例(比如用new生成的列表跨蟹,實例中的各種聲明的變量等)雳殊。“托管”的意思是Mono“應(yīng)該”自動地改變堆的大小來適應(yīng)你所需要的內(nèi)存窗轩,并且定時地使用垃圾回收(Garbage Collect)來釋放已經(jīng)不需要的內(nèi)存。關(guān)鍵在于座咆,有時候你會忘記清除對已經(jīng)不需要再使用的內(nèi)存的引用痢艺,從而導(dǎo)致Mono認(rèn)為這塊內(nèi)存一直有用,而無法回收介陶。profile可以檢測到.并且需要手機(jī)查找才正常,經(jīng)常需要優(yōu)化的部分.

3: 代碼文件的內(nèi)存.如lua腳本本身的內(nèi)存.C#泛型類的內(nèi)存,C++層會將泛型編譯成靜態(tài)類型就多出很多文件,盡量注意不要使用太多泛型模板類,shader寫的一個,但是編譯成很多份的文件等,都是代碼文件會占用的內(nèi)存.
程序代碼包括了所有的Unity引擎堤舒,使用的庫,以及你所寫的所有的游戲代碼哺呜。在編譯后舌缤,得到的運行文件將會被加載到設(shè)備中執(zhí)行,并占用一定內(nèi)存某残。這部分內(nèi)存實際上是沒有辦法去“管理”的国撵,它們將在內(nèi)存中從一開始到最后一直存在。一個空的Unity默認(rèn)場景玻墅,什么代碼都不放介牙,在iOS設(shè)備上占用內(nèi)存應(yīng)該在17MB左右,而加上一些自己的代碼很容易就飆到20MB左右澳厢。想要減少這部分內(nèi)存的使用环础,能做的就是減少使用的庫囚似。

4: 第三方庫的占用的內(nèi)存,也被稱為用戶管理的內(nèi)存,但是已經(jīng)和unity的內(nèi)存關(guān)系上完全無關(guān)了,如自己使用C++編譯的庫,tolua占用的內(nèi)存,lua文件占用的內(nèi)存(這個不是unity管理的),lua占用的內(nèi)存. 并且unity編輯器的profile無法檢測到.

優(yōu)化重點以及方向

unity托管內(nèi)存>第三方庫(主要是lua優(yōu)化)>unity底層優(yōu)化>代碼文件.

unity托管內(nèi)存(用戶管理內(nèi)存)-->

VM : mono的一個VM內(nèi)存池,虛擬機(jī)的內(nèi)存池.VM內(nèi)存會返回內(nèi)存給OS內(nèi)存,當(dāng)一塊內(nèi)存 GC 6次沒有被訪問到,就會將內(nèi)存放回給OS
GC :
分代式內(nèi)存回收
GC機(jī)制考量,
Throughput(回收能力):一次GC會回收到多少內(nèi)存
pause times(暫停時長):一次GC對主線程影響多大,會讓主線程暫停多少毫秒
Fragmentation(碎片化):一次GC內(nèi)存回收之后,會讓整塊內(nèi)存的碎片化增加多少,即不連續(xù)內(nèi)存會增加多少.
Mutator overhead(額外消耗):回收本身有消耗,需要考量這個消耗有多大.
Soalability(可擴(kuò)展性):多核多線程時會不會有其他bug
Portability(可移植性):在其他平臺上面是否可以移植

目前GC:
unity現(xiàn)在使用的是:Boehm(Non-generational)非分代式,(Non-compaction)非壓縮方式,內(nèi)存回收機(jī)制,是所有內(nèi)存同一放在一起的.造成主線程的卡頓

下一代GC:
Incremental GC(漸進(jìn)式GC),分幀去做GC回收,GC時長還是一樣的,但是會避免系統(tǒng)卡頓
目前已轉(zhuǎn)向IL2CPP(升級的Boehm)了.

問題:內(nèi)存下降,但是總體的內(nèi)存池還是上升了,為什么?
是代碼碎片化導(dǎo)致的.因為有一塊內(nèi)存一直插不進(jìn)去當(dāng)前內(nèi)存池里面,只能另行開辟內(nèi)存.也就是內(nèi)存碎片化沒有被壓縮.優(yōu)化建議,先去對大型內(nèi)存創(chuàng)建和釋放,再對小型內(nèi)存進(jìn)行創(chuàng)建和釋放.
Zimbie Memory(僵尸內(nèi)存,別名就叫做臟內(nèi)存,無用內(nèi)存)
指內(nèi)存從開啟游戲到游戲關(guān)閉只用了一次內(nèi)存.
沒有被釋放,內(nèi)存也沒有泄露,也沒辦法使用.
內(nèi)存泄漏指得是沒有任何人可以訪問和管理到它,也沒法釋放掉.
優(yōu)化建議:
不要覺得 obj == null就是釋放掉內(nèi)存了,顯示調(diào)用destroy方法才可以釋放掉.
要常用struct不要用class
Pool In Pool (池中池) 高頻使用的小部件需要建立一個內(nèi)存池,不要頻繁的去創(chuàng)建銷毀
Closures and anonymous methods (閉包和匿名函數(shù),協(xié)程) 這些東西最終在C++層全部new成一個class了,優(yōu)化建議:不要用.關(guān)于協(xié)程的優(yōu)化建議:用的時候創(chuàng)建,及時銷毀.再用時,再創(chuàng)建,再銷毀.
配置表優(yōu)化,優(yōu)化建議,采用C++管理內(nèi)存,使用C#接口以及Lua接口去查詢,而不是在c#和Lua里面保存內(nèi)存,不要在c#和Lua里面重新全部記錄.例如:從C++接過配置表對象時,在c#里面再保存一份,這是錯誤的方式.
Singleton 單例慎用,僅在必要時用,最好不要用單例模板,太坑爹的設(shè)計了,難用不說還特么代碼難看懂,惡心.

這個地方嚴(yán)重指責(zé)unity的GC機(jī)制,一直再說歷史原因什么的,現(xiàn)在也不做內(nèi)存壓縮,程序用著這個挺惡心的.

第三方庫(主要是lua優(yōu)化)-->

需要查看tolua源碼以及C++基礎(chǔ),然后在tolua的基礎(chǔ)上面做優(yōu)化,需要的個人能力比較強(qiáng).
以及使用C++庫作為插件導(dǎo)入進(jìn)unity里面使用.

unity底層代碼優(yōu)化方向-->

底層會根據(jù)類型將內(nèi)存分配到不同的Allooator的池子里面,使用GetRuntimeMemory
profiler中Memory一項中的Used Total 和 Reserved Total會保持相同的上升或者下降,如果不一致,那就是出bug了.
Used Total 表示當(dāng)前你使用了多少內(nèi)存
Reserved Total表示unity申請了多少內(nèi)存,將要使用到的內(nèi)存
1: Scene中的GameObject太多,則內(nèi)存會暴漲.如果在場景中創(chuàng)建了一個GameObject,底層C++會創(chuàng)建一個或者多個object(記錄component),去記錄這個GameObject的信息.是程序的優(yōu)化重點,建議:盡量少創(chuàng)建GameObject,并且無用GameObject盡量干掉,優(yōu)化GameObject個數(shù).
2: Audio中會有個緩存池(DSP buffer),需要用戶設(shè)置,填充滿就會向CPU發(fā)送播放指令,發(fā)送完播放指令才會播放.設(shè)置的過大,則音頻填充滿就會時間過長,聲音延遲,設(shè)置的過小,就會向CPU頻繁發(fā)送.優(yōu)化建議:測試音頻播放密集時與不密集時的樣本,并進(jìn)行大小變換設(shè)置.
Force to mono,雙聲道音頻設(shè)置,雙聲道概念:左右聲道播放的不一致的聲音.優(yōu)化建議,設(shè)置為單聲道.
音頻格式Format,Mac/iOS上面的音頻設(shè)置為mp3,有硬件支持.
音頻壓縮格式Compression Format:在哪種情況下使用哪種形態(tài),需要去unity官方手冊上面查詢.
3: CodeSize,模板泛型的亂用,會導(dǎo)致打包速度,并且靜態(tài)代碼量增多.模板泛型,(il2cpp)會在C++層將泛型全部轉(zhuǎn)成靜態(tài)類型的C++,會變的很大.(一個文件2-3m已經(jīng)很多了吧,官方視頻上說有25M! ...)
4: AssetBundle
typetree,序列化的時候會生成一個typetree,反序列化的時候會根據(jù)這個typetree反序列化.
關(guān)閉typetree內(nèi)存會減小,包大小會減小,build和運行時會變快.
Lz4 壓縮方式,快速壓縮,包體大Lzma上面30%,不要用Lzma,lzma會增大內(nèi)存等等副作用.
asset會有頭記錄部分,以及實際的數(shù)據(jù)部分,如果每一個都打成ab則有可能發(fā)生,頭記錄部分比實際數(shù)據(jù)部分還要大,建議是1-2M,5G以后可以加大.
5:Resource 文件夾 ,打進(jìn)包的時候會做一個紅黑樹(R-B Tree),會檢索數(shù)據(jù)在什么位置,這個里面的數(shù)據(jù)很大,則紅黑樹就會很大.優(yōu)化建議:不要放大量數(shù)據(jù)就行了,用ab替換.
6:Texture
upload buffer 這個數(shù)據(jù)表示填滿之后向GPU發(fā)送一次,建議測試并平均該值
R/W read and write 一般情況下不要開,開啟情況會在顯存和內(nèi)存中各一份.
mip maps UI情況下不要開就行了.
7: mesh
R/W 一般情況下不要開. compression在某些unity版本上面開了比不開占用更多內(nèi)存.

(tips:加快 unity編輯器下腳本編譯速度https://www.xuanyusong.com/archives/4474)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市线得,隨后出現(xiàn)的幾起案子饶唤,更是在濱河造成了極大的恐慌,老刑警劉巖贯钩,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件募狂,死亡現(xiàn)場離奇詭異,居然都是意外死亡魏保,警方通過查閱死者的電腦和手機(jī)熬尺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谓罗,“玉大人粱哼,你說我怎么就攤上這事¢菰郏” “怎么了揭措?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長刻蚯。 經(jīng)常有香客問我绊含,道長,這世上最難降的妖魔是什么炊汹? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任躬充,我火速辦了婚禮,結(jié)果婚禮上讨便,老公的妹妹穿的比我還像新娘充甚。我一直安慰自己,他們只是感情好霸褒,可當(dāng)我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布伴找。 她就那樣靜靜地躺著,像睡著了一般废菱。 火紅的嫁衣襯著肌膚如雪技矮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天殊轴,我揣著相機(jī)與錄音衰倦,去河邊找鬼。 笑死梳凛,一個胖子當(dāng)著我的面吹牛耿币,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播韧拒,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼淹接,長吁一口氣:“原來是場噩夢啊……” “哼十性!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起塑悼,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤劲适,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后厢蒜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霞势,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年斑鸦,在試婚紗的時候發(fā)現(xiàn)自己被綠了愕贡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡巷屿,死狀恐怖固以,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嘱巾,我是刑警寧澤憨琳,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站旬昭,受9級特大地震影響篙螟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜问拘,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一遍略、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧骤坐,春花似錦墅冷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驰唬。三九已至顶岸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叫编,已是汗流浹背辖佣。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留搓逾,地道東北人卷谈。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像霞篡,于是被迫代替她去往敵國和親世蔗。 傳聞我的和親對象是個殘疾皇子端逼,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容