<aside>
💡 我的博客:萤火之森 ,所有的公开笔记放在:公开笔记
</aside>
Best practice guides
什么是内存
- 物理内存
- 虚拟内存
- 内存交换
- 移动设备不支持内存交换
- iOS 可以进行内存压缩
- Android 没有内存压缩能力
内存杀手 low memory killer(AKA lmk)
- 内存不足时,killer 会出现,从上图底层一层一层地向上杀。(Cached-Previous-Home...)
Unity 内存管理
- Unity 是一个 C++ 引擎
- 底层代码完全由 C++ 写成
- 通过 Wrapper 提供给用户 API
- 用户代码会转换为 CPP 代码 (il2cpp)
- Unity 内存按照分配方式分为:
- Native Memory
- Managed Memory
- Editor & Runtime 是不同的
- 不止是统计看到的内存大小不同,甚至是内存分配时机和方式也不同
- Asset 在 Runtime 中如果不读取,是不会进内存的,但 Editor 打开就占内存。因为 Editor 不注重 Runtime 的表现,更注重编辑器中编辑时的流畅。
- 但如果游戏庞大到几十个 G,如果第一次打开项目,会消耗很多时间,有的大的会几天,甚至到一周。
- Unity 内存按照管理者分为:
- Unity 检测不到的内存
- 用户分配的 native 内存
- 自己写的 Native 插件(C++ 插件), Unity 无法分析已经编译过的 C++ 是如何去分配和使用内存的。
- Lua 完全由自己管理内存,Unity 无法统计到内部的使用情况。
Unity Native Memory 管理
Unity 重载了所有分配内存的操作符(C++ alloc、new),使用这些重载的时候,会需要一个额外的 memory label (Profiler-shaderlab-object-memory-detail-snapshot,里面的名字就是 label:指当前内存要分配到哪一个类型池里面)
- 使用重载过的分配符去分配内存时,Allocator 会根据你的 memory label 分配到不同 Allocator 池里面,每个 Allocator 池 单独做自己的跟踪。因此当我们去 Runtime get memory label 下面的池时就可以问 Allocator,里面有多少东西 多少兆。
- Allocator 在 NewAsRoot (Memory “island”(没听清)) 中生成。在这个 Memory Root 下面会有很多子内存:shader:当我们加载一个 Shader 进内存的时候,会生成一个 Shader 的 root。Shader 底下有很多数据:sub shader、Pass 等会作为 memory “island” (root) 的成员去依次分配。因此当我们最后统计 Runtime 的时候,我们会统计 Root,而不会统计成员,因为太多了没法统计。
- 因为是 C++ 的,因此当我们 delete、free 一个内存的时候会立刻返回内存给系统,与托管内存堆不一样。