Unity 性能优化 之 内存优化

Unity 之 性能优化 -- 内存优化

Unity 中的内存

  • 托管内存:

    • 使用托管堆或垃圾收集器自动分配和管理的内存;
    • 包括托管堆内存、脚本堆栈内存和虚拟机内存三个部分,其中托管堆内存为优化的主要部分。
  • C#非托管内存:

    • 在C#下与Unity COllection命名空间及包结合使用,允许访问Native内存层;
    • 使用Marshal类或者unsafe代码块可以在C#中分配非托管内存,其不使用垃圾收集器管理,需要手动释放。
  • Native内存:

    • Unity用于运行引擎的C++内存,Native内存通常与使用底层API或者调用外部原生库时相关联;
    • 例如,当通过Unity的底层API与图形渲染管线进行交互时,可能需要使用Native内存来传输数据。

除了Unity所需要的计算内存,渲染功能还需要对应显存,而在移动端,显存往往也与内存共享。

对于不同平台,操作系统会以不同方式分配出对应的应用程序框架内存、第三方库内存和系统内存。

内存相关工具

  • Memory Profiler中可以进行:

    • 在Editor中检查Runtime内存开销情况;
    • 内存占用细节可以精确到具体的Object,并索引到场景中。
  • ProjectSettings中的Memory Settings:

    • 可以进行Memory Allocator的设置;
    • 在Unity中,Memory Allocator(内存分配器)是负责在运行时管理内存分配和释放的机制。Unity提供了几种不同的内存分配器,每种都有不同的用途和性能特点,开发人员可以根据具体需求选择合适的内存分配器;
    • Memory Allocator清单详见官方文档
  • UPR工具中内存快照:

    • 可以脱离编辑器,模拟运行时的内存信息;
    • 可以比对运行时多帧的内存快照差异;
    • 模拟移动端硬件环境。
  • xCode




Dirty Size数值非常重要:它表示物理内存中不能被复用或者被卸载的内存块,一旦超过一定大小IOS程序就回自动退出。【1G内存手机上大概是700M,2G内存是1.4G】

这个数值直接关乎应用程序在长期运行中会不会崩溃,所以需要关注它的峰值是否超过警戒线,并且有没有下降的过程。



Unity 中Allocator

Unity 中内存分配器

  • Main Allocators:绝大多数内存分配时使用的,包括:主线程,渲染资源相关,文件Catch等不同用途下的配器。
  • Fast Per Thread Temporary Allocators:线程上使用的临时分配器,包括各工作线程的栈分配器(如:音乐,渲染,预加载,烘焙)
  • Fast Thread Shared Temporary Allocators:线程间共享的临时分配器
  • Profiler Allcators:用于Profiler的分配器








内存指标术语与进程内存结构

  • Used:表示Page正在被进程使用,内存页也映射到了物理内存中。
  • Free:表示此内存页可用,并且没有映射到物理内存中。
  • Cache:表示此页被操作系统用于缓存的可用内存。
    • 虽然内存页已经被映射到内存中,但此页可能近期没有被访问。
    • 若Free页数量低于阈值时,操作系统会从Cache中获取内存,并经Cache页中的数据交换到磁盘,然后对Cache页进行清理,并将其标记为Free页。

Region:一块共享内存状态和保护级别的连续地址空间。它可以由具有不同状态的多个Page组成。

Region状态:

  • Resident:代表其中的Page已经在物理内存中
  • Dirty:代表Page已修改但未写入磁盘
  • Wired:代表永远不会交换到辅助存储的固定Page段
  • Committed:代表已分配的内存区域,其地址不能被其他分配使用。
  • Reserved:该状态的Region保存地址空间为将来使用
  • Free:空闲内存区

进程内存结构


移动平台内存经验值数据参考


通用游戏类型:数值的上下限分别代表了在移动平台的高-低配置数据差异

  • 其中RenderTexture会根据目标设备的分辨率不同会有差异变化(上图是1080P下的经验数值)。
  • 一些下限为0的参数,为不使用此功能为最佳。
  • 一些带有小于号<的参数,为数值越小越好。
  • System.XXX总和:此项的内存开销,基本上来着用户的配置数据表与C#层的基础类型变量的定义。一些开发者习惯把所有的配置数据全部缓存进来,会导致此项内存开销过高。尤其是一写纯文本数据,若需要则建议使用二进制方式分级缓存读取。
  • 其他各类对象单项:是指C#层的对象,主要会是一下Component和GameObject派生出来的对象,不仅需要关注这些对象的内存大小,还需要关注个数。

本文整理自:Metaverse大衍神君《Unity性能优化》

相关推荐
PineappleCoder5 小时前
工程化必备!SVG 雪碧图的最佳实践:ID 引用 + 缓存友好,无需手动算坐标
前端·性能优化
DemonAvenger12 小时前
Redis发布订阅模式:打造实时消息通信系统的实践指南
数据库·redis·性能优化
技术小甜甜13 小时前
[Godot] 解决导出APK安装失败的常见问题:深入分析与调试方法
游戏引擎·godot·游戏开发
拾忆,想起15 小时前
设计模式:软件开发的可复用武功秘籍
开发语言·python·算法·微服务·设计模式·性能优化·服务发现
Henry Zhu12316 小时前
VPP中ACL源码详解第六篇:多核和性能优化实现以及调试与观测
运维·网络·网络协议·计算机网络·性能优化
卓码软件测评16 小时前
CMA/CNAS软件测评机构:【Gatling数据库性能关联测试JDBC连接和SQL执行时间监控】
数据库·sql·测试工具·性能优化·测试用例
allk5517 小时前
Android 屏幕适配全维深度解析
android·性能优化·界面适配
老朱佩琪!17 小时前
Unity桥接模式
unity·设计模式·c#·桥接模式
技术小甜甜17 小时前
[Godot][入门] 安装与版本选择:3.x 还是 4.x?(按项目类型一键决策)
游戏引擎·godot·游戏开发·2d
陈言必行18 小时前
Unity 之 物理引擎中三种刚体力施加方式详解
unity·游戏引擎