Unity ECS创建大量实体未耗尽内存却触发AddEmptyChunk段错误
问题:内存未耗尽时Unity Entities的AddEmptyChunk触发段错误
我编写了一个测试程序,每帧创建100个带有Buffer组件的实体,代码如下:
void Execute(Entity projectileEntity, [ChunkIndexInQuery] int chunkIndex, ref LocalTransform transform, in Projectile projectile) { for(int j = 0; j < 100; j++) { var e = ECBWriter.CreateEntity(chunkIndex); var as_path = ECBWriter.AddBuffer<ASN>(chunkIndex, e); for(uint i = 0; i < 10; i++){ as_path.Add(new ASN { routerID = i }); } } }
将程序编译后在Linux服务器运行,一段时间后,当创建约2×10⁸个实体、生成约1×10⁶个Chunk且占用22GB内存时崩溃(服务器总内存为128GB)。报错信息如下:
编辑器版本2022.3.5f1c1,Entities版本1.0.14
Caught fatal signal - signo:11 code:1 errno:0 addr:(nil) Segmentation fault (core dumped)
编辑器版本2021.3.11f1c2,Entities版本0.51.1-preview.21
Caught fatal signal - signo:11 code:1 errno:0 addr:(nil) Obtained 6 stack frames. #0 0x007f6752ad9980 in funlockfile #1 0x007f6705882ac4 in Unity.Entities.ChunkDataUtility.AddEmptyChunk(Unity.Entities.Archetype* archetype, Unity.Entities.Chunk* chunk, Unity.Entities.SharedComponentValues sharedComponentValues) -> void_08f2b62234a514a789dc69881ac7811a #2 0x007f6705890f29 in Unity.Entities.EntityComponentStore.GetChunkWithEmptySlotsWithAddedComponent(Unity.Entities.EntityComponentStore* this, Unity.Entities.Chunk* srcChunk, Unity.Entities.ComponentType componentType, int sharedComponentIndex) -> Unity.Entities.Chunk*_08f2b62234a514a789dc69881ac7811a #3 0x007f67058dfaf0 in Unity.Entities.EntityDataAccess.AddComponentDuringStructuralChange(Unity.Entities.EntityDataAccess* this, Unity.Entities.Entity entity, Unity.Entities.ComponentType componentType, ref Unity.Entities.SystemHandleUntyped originSystem) -> bool_08f2b62234a514a789dc69881ac7811a #4 0x007f67058ddd14 in Unity.Entities.EntityCommandBuffer.EcbWalker`1<Unity.Entities.EntityCommandBuffer.PlaybackProcessor>.ProcessChain(Unity.Entities.EntityCommandBuffer.EcbWalker`1<Unity.Entities.EntityCommandBuffer.PlaybackProcessor>* this, Unity.Entities.ECBChainPlaybackState* chainStates, int currentChain, int nextChain) -> void_08f2b62234a514a789dc69881ac7811a #5 0x000000404b8e18 in (wrapper managed-to-native) object:wrapper_native_0x7f6705982900 (intptr,int,intptr,int,int) Segmentation fault (core dumped)
请问为何在内存未耗尽的情况下,AddEmptyChunk会触发段错误?
分析与解答
1. Chunk数量超限引发内部索引溢出
Unity Entities的Chunk管理系统中,部分内部数据结构使用32位整数追踪Chunk的索引或计数。当Chunk数量达到约1×10⁶时,部分计数器可能触发溢出,导致空指针引用(对应报错中的addr:(nil)),进而引发段错误。
2. ECB批量操作的结构性变更冲突
每帧通过ECBWriter批量创建实体并添加Buffer组件,高频的结构性变更(创建实体、添加Buffer)会导致ECB回放时频繁调用Chunk分配逻辑。当Chunk数量过大时,AddEmptyChunk在访问或更新全局Chunk管理链表/数组时,可能因索引溢出指向无效内存,触发空指针访问。
3. 旧版本Entities的已知Bug
你使用的两个Entities版本均存在大数量Chunk管理的已知问题:
- 0.51.x预览版稳定性不足,对超大规模场景的Chunk处理逻辑存在缺陷;
- 1.0.14正式版的后续更新日志中,明确提到修复了“大量Chunk下的空指针崩溃”问题,比如1.0.17+版本优化了Chunk分配的内存管理逻辑。
4. 内存碎片化的间接影响
虽然总内存未耗尽,但大量小Chunk的创建会导致内存碎片化,使得AddEmptyChunk尝试分配连续内存块时失败,返回空指针后未做校验,最终触发段错误。
解决建议
- 升级Entities版本:更新到最新的LTS兼容版本(如1.0.20+),官方已修复大量此类大场景下的Chunk管理崩溃问题;
- 优化实体创建逻辑:避免每帧创建大量小实体,尝试合并同类实体的Buffer数据,或使用对象池复用实体;
- 调整Chunk容量:通过
[ChunkCapacity]属性自定义Archetype的Chunk容量,减少总Chunk数量; - 监控内部状态:使用Entities的Profiler工具追踪Chunk数量、结构性变更频率,提前发现异常阈值。
内容的提问来源于stack exchange,提问作者Kaihui Gao
相关产品推荐
相关产品推荐

