最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Unity ECS 內(nèi)存分配器原理詳解

2021-06-08 10:56 作者:博毅創(chuàng)為  | 我要投稿

ECS 為什么會高效,性能好,Entity的內(nèi)存布局與分配就是非常重要的部分,今天我們一起來分析一下Unity ECS 架構(gòu)里面如何來做高效的內(nèi)存分配器。這種思路也可以給我們做內(nèi)存分配提供很好的一個思路。

1: ECS 里面基本的一些概念

Unity ECS框架里面有幾個重要的概念:

Entity, ComponentData, System,Archetype, EntityManager, World;

ComponentData:

組件數(shù)據(jù),開發(fā)的時候,可以把每個功能相關(guān)的數(shù)據(jù)放到ComponentData里面。

Entity:

對象實(shí)體,純數(shù)據(jù)對象,里面包含了一個個的ComponentData, 每個相關(guān)功能使用的數(shù)據(jù)我們放Entity的ComponentData里面, 如圖:

ystem:

具體算法邏輯的實(shí)現(xiàn),System算法數(shù)據(jù)基于Entity里面對應(yīng)處理的ComponentData。游戲引擎每次Update的時候,System都會根據(jù)每個Entity里面的它使用的ComponentData, 來更新數(shù)據(jù)完成計算。

EntityManager:

負(fù)責(zé)Entity相關(guān)類型信息,對象實(shí)體的創(chuàng)建與管理。

Archetype:

Entity是由多個ComponentData組成的,每種Entity類型都會對應(yīng)一個Archetype, 里面描述了這個Entity類型以及相關(guān)的布局。Archetype由EntityManager創(chuàng)建出來,創(chuàng)建出來后這個類型的Entity的大小,包含的組件數(shù)據(jù),內(nèi)存布局都確定了。

World:

世界包含多個Entity組成Entity群體,通過世界把這些Entity群體孤立起來。Unity里面可以同時擁有多個不同的世界, 每個世界獨(dú)立包含EntityManager, 與Systems, 在世界里面創(chuàng)建出來的一個Entity,只屬于這個世界。世界里每個System也只能迭代一個世界里面的Entity實(shí)體數(shù)據(jù)。你可以創(chuàng)建多個World。

總結(jié)一下Unity ECS的使用步驟與邏輯關(guān)系:

(1) 創(chuàng)建一個ECS的World;

(2) 使用World的EntityManager為不同Entity類型創(chuàng)建出來Archetype;

(3) 基于Archetype, 我們創(chuàng)建出來Entity內(nèi)存對象, 并初始化Entity里面每個ComponentData數(shù)據(jù);

(4)為ECS World編寫System算法,World會調(diào)用System算法來迭代每個Entity里的相關(guān)ComponentData;

2: ECS 高效的內(nèi)存模型與布局

作為架構(gòu)師,設(shè)計框架數(shù)據(jù)結(jié)構(gòu)由為關(guān)鍵。特別對于游戲開發(fā),要處理迭代成百上千個游戲物體。高效的內(nèi)存模型與布局如何實(shí)現(xiàn)? 首先要明白怎么樣布局內(nèi)存才會高效。內(nèi)存模型布局高效主要從兩個方面來考慮:

1:內(nèi)存對齊。

CPU訪問不同地址的內(nèi)存數(shù)據(jù)的時候,如果內(nèi)存地址基于2^n 數(shù)據(jù)對齊(n根據(jù)CPU而定),訪問最為高效。例如我們以16字節(jié)數(shù)據(jù)對齊,那么對象內(nèi)存開始排布的時候, 從地址能整除16的內(nèi)存位置開始排布。高效的內(nèi)存布局,對象實(shí)例內(nèi)存地址要對齊,對象實(shí)例里面的每個數(shù)據(jù)成員內(nèi)存地址也要對齊。Entity的內(nèi)存分配與內(nèi)存布局, 在創(chuàng)建Entity的時候,ECS系統(tǒng)就會注意Entity的內(nèi)存對齊,同時也會注ComponentData在Entity里面排布的內(nèi)存對齊,如果沒有對齊,就會空一些出來。比如16字節(jié)對齊,一個ComponentData只有14個字節(jié),實(shí)際上排布下一個ComponentData的時候是從16字節(jié)開始排布的。

2: CPU通過地址來取到內(nèi)存數(shù)據(jù)的時,數(shù)據(jù)排布一起取的速度會更快。

ECS天然就具有這種優(yōu)勢。所有的邏輯代碼迭代都是基ComponentData的,也就是算法迭代訪問處理的數(shù)據(jù)都在一起,在一個ComponentData里面。這樣訪問數(shù)據(jù)高效,避免了地址的來回跳轉(zhuǎn)。

3: Entity內(nèi)存分配器 Chunk的設(shè)計

大量的Entity的創(chuàng)建與銷毀,大量不同類型的數(shù)據(jù)對象交叉創(chuàng)建,很容易造成內(nèi)存碎片。何為內(nèi)存碎片?給大家舉個例子,對象A,對象B(100字節(jié)),對象C連續(xù)排布,對象B銷毀,內(nèi)存釋放,同時又請求分配對象D(80字節(jié)),系統(tǒng)在原來對象B的地方把一塊內(nèi)存分配給對象D,還剩了一小塊內(nèi)存(20字節(jié))。而這一小塊內(nèi)存,無法分配給當(dāng)前系統(tǒng)的任何一個對象,這樣,這小快內(nèi)存就再也無法使用了,造成內(nèi)存碎片,隨著系統(tǒng)不斷運(yùn)行,隨著更多大量的創(chuàng)建與釋放,內(nèi)存碎片越來越多,分配/釋放效率也越來越低。最終讓系統(tǒng)越來越慢。解決這種大量創(chuàng)建與銷毀,我們一般采用Cache內(nèi)存池來做。那Unity ECS架構(gòu)里面內(nèi)存池是如何設(shè)計的呢?接下來我們來分析ECS里面基于Chunk的內(nèi)存分配器。不同的Archetype,所對應(yīng)的Entity的內(nèi)存不一樣,系統(tǒng)可能有N中不同的Archetype,而且Archetype是用戶根據(jù)組件數(shù)據(jù)組合創(chuàng)建而來。

綜上Unity ECS 是這樣設(shè)計內(nèi)存分配緩存池:

(1) 基于固定大小的Chunk來做內(nèi)存緩存池。每個Chunk大小為16KB(引用來自于UnityECS 文檔)

(2) 當(dāng)Archetype 確定后,Entity的內(nèi)存大小就確定下來,每個Chunk能分配的當(dāng)前的Entity數(shù)目就能確定下來?;贏rchetype創(chuàng)建Entity的時候,首先從內(nèi)存池里面拿一個Chunk, 然后根據(jù)每個Chunk可創(chuàng)建Entity數(shù)目,從Chunk里面把Entity分配出去,如果chunk分配完畢,從chunk內(nèi)存緩存池里面再拿一個Chunk。由于基于Archetype創(chuàng)建,這個Archetype的所有Entity內(nèi)存大小都是一樣的,等釋放的時候,我們就可以基于Archetype把Entity緩存起來,重復(fù)使用之前的Entity。

對于OS而言,ECS框架基于chunk來分配和釋放內(nèi)存,避免了內(nèi)存碎片(大小都一樣)。對于ArcheType而言,又基于特定ArcheType的Entity來做內(nèi)存緩存,分配和釋放都非常高效。

看完Unity ECS的架構(gòu)設(shè)計與內(nèi)存布局,我們在其他地方做ECS架構(gòu)設(shè)計(游戲服務(wù)器)就有了一個很好的參考,設(shè)計萬變不離其中,大家可以好好體會一下。

更多教學(xué)視頻以及素材源碼
https://bycwedu.vipwan.cn/promotion_channels/829468798


Unity ECS 內(nèi)存分配器原理詳解的評論 (共 條)

分享到微博請遵守國家法律
怀化市| 吴旗县| 隆昌县| 石台县| 桐城市| 大名县| 南汇区| 泾源县| 江口县| 汝阳县| 文水县| 通化县| 徐汇区| 安塞县| 南昌市| 竹北市| 洪江市| 台江县| 黄浦区| 昌邑市| 沙田区| 固始县| 河西区| 平罗县| 台前县| 盐池县| 若羌县| 建湖县| 长子县| 宁强县| 调兵山市| 曲周县| 织金县| 鸡泽县| 桃园县| 夏河县| 黄骅市| 合山市| 汉中市| 儋州市| 康乐县|