Unity中的内存
- 托管内存:主要是指使用托管堆或者垃圾收集器自动分配和管理的内存,也包括脚本堆栈与虚拟机内存;
- C#非托管内存:可以在C#下与Unity Colloection名字空间和包结合使用,不使用垃圾收集器管理的内存部分;
- Native内存:Unity用于运行引擎的C++内存;
Unity内存查看工具
- Unity Profiler
- Memory Profiler(Unity 2021+)
Unity的Native内存分配
Unity底层是C++实现的,一般来说,游戏引擎都不会直接通过melloc或new来直接分配内存,而是至少在其之上封装一层来做内存管理、统计与检查等工作;
Unity中C++层会根据用途不同,抽象成不同的Allocator来进行内存分配,通过不同的Memory label标签与Owner ship的设置进行标记与追踪,通过Memory manager进行统一的管理;
Allocator的分类
按用途分类
- Main Allocators:绝大多数内存使用的分配器
- Fast Per Thread Temporary Allocators:线程使用的临时分配器,比如各个线程的栈分配器
- Fast Thread Shared Temporary Allocators:线程间内存共享的临时分配器
- Profiler Allocators
这些都是用途抽象出来的分配器,在Unity引擎代码中并没有对应的分配器的类;
在Unity代码中是根据分配算法分类的分配器;
按底层类型分类
- Unity Default Allocator
- Bucket Allocator
- Dynamic Heap Allocator
- Dual Thread Allocator
- TLS Allocator(Thread Local Storage)
- Stack Allocator
- Thread Safe Linar Allocator
- …
与按类型分类的分配器是一对多的关系,也就是按类型分配的分配器底层都是按算法分类的分配器实现的;
主要的底层分配器
BucketAllocator桶分配器
DynamicHeapAllocator动态堆分配器
DualThreadAllocator
TLS Stack Allocator
Thread Safe Linear Allocator
主线程分配回退流程
工作线程分配回退流程
托管内存优化
- Boxing Allocation装箱操作
- String字符串拼接
- 闭包分配
- 避免使用Linq库
- Unity中有NonAlloc的方法使用NonAlloc方法
- Unity.Object.FindObjectsOfType、UnityEngine.Component.GetComponentsInParent等返回对象列表的方法都有堆内存分配
- 成员变量访问形式改用方法而不是点变量,如UnityEngine.Mesh.vertices => UnityEngine.Mesh.GetVertices