Unity ECS 内存分配器原理详解

ECS 为什么会高效,性能好,Entity的内存布局与分配就是非常重要的部分,今天我们一起来分析一下Unity ECS 架构里面如何来做高效的内存分配器。这种思路也可以给我们做内存分配提供很好的一个思路。

对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习unity的零基础小白,也有一些正在从事unity开发的技术大佬,欢迎你来交流学习。

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

Unity ECS框架里面有几个重要的概念:

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

ComponentData:

组件数据,开发的时候,可以把每个功能相关的数据放到ComponentData里面。

Entity:

对象实体,纯数据对象,里面包含了一个个的ComponentData, 每个相关功能使用的数据我们放Entity的ComponentData里面, 如图:

(Entity内存对象布局示意图)

System:

具体算法逻辑的实现,System算法数据基于Entity里面对应处理的ComponentData。游戏引擎每次Update的时候,System都会根据每个Entity里面的它使用的ComponentData, 来更新数据完成计算。

EntityManager:

负责Entity相关类型信息,对象实体的创建与管理。

Archetype:

Entity是由多个ComponentData组成的,每种Entity类型都会对应一个Archetype, 里面描述了这个Entity类型以及相关的布局。Archetype由EntityManager创建出来,创建出来后这个类型的Entity的大小,包含的组件数据,内存布局都确定了。

World:

世界包含多个Entity组成Entity群体,通过世界把这些Entity群体孤立起来。Unity里面可以同时拥有多个不同的世界, 每个世界独立包含EntityManager, 与Systems, 在世界里面创建出来的一个Entity,只属于这个世界。世界里每个System也只能迭代一个世界里面的Entity实体数据。你可以创建多个World。

总结一下Unity ECS的使用步骤与逻辑关系:

(1) 创建一个ECS的World;

(2) 使用World的EntityManager为不同Entity类型创建出来Archetype;

(3) 基于Archetype, 我们创建出来Entity内存对象, 并初始化Entity里面每个ComponentData数据;

(4)为ECS World编写System算法,World会调用System算法来迭代每个Entity里的相关ComponentData;

(Unity ECS 架构图)

2: ECS 高效的内存模型与布局

作为架构师,设计框架数据结构由为关键。特别对于游戏开发,要处理迭代成百上千个游戏物体。高效的内存模型与布局如何实现? 首先要明白怎么样布局内存才会高效。内存模型布局高效主要从两个方面来考虑:

1:内存对齐。

CPU访问不同地址的内存数据的时候,如果内存地址基于2^n 数据对齐(n根据CPU而定),访问最为高效。例如我们以16字节数据对齐,那么对象内存开始排布的时候, 从地址能整除16的内存位置开始排布。高效的内存布局,对象实例内存地址要对齐,对象实例里面的每个数据成员内存地址也要对齐。Entity的内存分配与内存布局, 在创建Entity的时候,ECS系统就会注意Entity的内存对齐,同时也会注ComponentData在Entity里面排布的内存对齐,如果没有对齐,就会空一些出来。比如16字节对齐,一个ComponentData只有14个字节,实际上排布下一个ComponentData的时候是从16字节开始排布的。

2: CPU通过地址来取到内存数据的时,数据排布一起取的速度会更快。

ECS天然就具有这种优势。所有的逻辑代码迭代都是基ComponentData的,也就是算法迭代访问处理的数据都在一起,在一个ComponentData里面。这样访问数据高效,避免了地址的来回跳转。

3: Entity内存分配器 Chunk的设计

大量的Entity的创建与销毁,大量不同类型的数据对象交叉创建,很容易造成内存碎片。何为内存碎片?给大家举个例子,对象A,对象B(100字节),对象C连续排布,对象B销毁,内存释放,同时又请求分配对象D(80字节),系统在原来对象B的地方把一块内存分配给对象D,还剩了一小块内存(20字节)。而这一小块内存,无法分配给当前系统的任何一个对象,这样,这小快内存就再也无法使用了,造成内存碎片,随着系统不断运行,随着更多大量的创建与释放,内存碎片越来越多,分配/释放效率也越来越低。最终让系统越来越慢。解决这种大量创建与销毁,我们一般采用Cache内存池来做。那Unity ECS架构里面内存池是如何设计的呢?接下来我们来分析ECS里面基于Chunk的内存分配器。不同的Archetype,所对应的Entity的内存不一样,系统可能有N中不同的Archetype,而且Archetype是用户根据组件数据组合创建而来。

综上Unity ECS 是这样设计内存分配缓存池:

(1) 基于固定大小的Chunk来做内存缓存池。每个Chunk大小为16KB(引用来自于UnityECS 文档)

(2) 当Archetype 确定后,Entity的内存大小就确定下来,每个Chunk能分配的当前的Entity数目就能确定下来。基于Archetype创建Entity的时候,首先从内存池里面拿一个Chunk, 然后根据每个Chunk可创建Entity数目,从Chunk里面把Entity分配出去,如果chunk分配完毕,从chunk内存缓存池里面再拿一个Chunk。由于基于Archetype创建,这个Archetype的所有Entity内存大小都是一样的,等释放的时候,我们就可以基于Archetype把Entity缓存起来,重复使用之前的Entity。

对于OS而言,ECS框架基于chunk来分配和释放内存,避免了内存碎片(大小都一样)。对于ArcheType而言,又基于特定ArcheType的Entity来做内存缓存,分配和释放都非常高效。

看完Unity ECS的架构设计与内存布局,我们在其他地方做ECS架构设计(游戏服务器)就有了一个很好的参考,设计万变不离其中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340