翻译:https://unity3d.com/cn/learn/tutorials/topics/best-practices/managed-memory

理解托管堆对 Unity 中的内存管理至关重要。 有关分析托管内存和如何优化内存的更多信息,请参阅了解 Unity 中的理解优化部分。

一、Assets

资产在运行时影响本机内存和托管内存。 在用户终止应用程序之前,Unity 运行时不会将托管内 存返回到操作系统进行重用。 如果托管堆变得过于支离破碎并耗尽可用内存,则它会增大。 由于这种不可预测的行为,知道资产如何占用托管内存是非常重要的:

  • 使用Destroy(myObject)来销毁一个对象并释放其内存。 将对象的引用设置为 null 并不会破坏它
  • 您应该将持久(long-term)对象设置为类,将临时(short-term)对象设置为结构。 结构不在堆上分配,因此不会进行垃圾回收。
  • 重用临时工作缓冲区以保持临时垃圾较低,而不是频繁分配。
  • 枚举数在退出之前不会清除其内存。
  • 您应该避免永无止境的协程,尤其是在 on 中分配大量托管内存时,因为协程会保持堆上的堆栈分配,直到协程结束。
    请阅读 Unity优化指南中的理解托管内存部分,以获得对托管堆(的更深入的理解。

二、IL2CPP & Mono

在 iOS 和 Android 上,在Player Settings 中选择 Mono 或 IL2CPP Scripting Backend。 要改变Scripting Backend,转到Player Settings窗口(菜单: 编辑项目设置播放器) ,向下滚动到其他设置部分,并选择 Mono 或 IL2CPP 从Scripting Backend下拉菜单。
注意: 从2017.3开始,要么选择 IL2CPP Scripting Backend,要么选择 Mono Scripting Backend。 然而,WebGL 和 UWP 都只支持 IL2CPP。 iOS 仍然支持 Mono Scripting Backend来进行快速迭代,但是你不能再向苹果提交 Mono (32位)应用程序了。

不同Scripting Backend的优缺点:
每一个脚本后端都有其优缺点,这些优缺点会影响你的决定,哪一个是适合你的情况的正确选择:

IL2CPP

  • 与 Mono 相比,代码生成得到了很大的改进。
  • 从上到下调试 c + + 中的脚本代码是可能的。
  • 您可以启用Engine code stripping以减少代码大小。
  • 构建时间比使用 Mono 要长。
  • 只支持Ahead of Time(AOT)编译。

Mono

  • 比 IL2CPP 更快的构建时间。
  • 由于Just In Time compilation(JIT) ,支持更多的托管库。
  • 支持运行时代码执行。
  • 必须装运管理的组件(.dll files that mono- or .net- produces)。

提示: 您应该使用 IL2CPP 来开发和发布您的项目。 如果使用 IL2CPP 的迭代次数太慢,那么在开发过程中临时切换到 Mono Scripting Backend,以提高迭代速度。
注意: Player Settings中的默认目标架构是为发布版本而优化的。 在开发过程中使用这个默认值会增加你的构建时间,因为 Unity 会为所选择的每个目标架构构建二进制文件:
Android Player Settings中默认的目标架构是 armv7和 x86,带有 IL2CPP 和 Mono Scripting Backend
iOS Player Settings中的默认架构是 armv7和 arm64,带有 IL2CPP Scripting Backend

Code stripping in Unity:
代码大小直接影响磁盘空间和运行时内存。 很重要的一点是,Unity 会从代码库中删除任何您没有使用的代码路径。 在构建过程中,Unity 自动条带化代码,在两个不同的层次上工作:
1.Managed code stripping
Unity 条带方法级别上的托管代码。 要改变剥离级别,转到播放机设置窗口,向下滚动到其他设置部分,找到剥离级别下拉菜单并选择剥离程序集。
Unitylinker 从中间语言(IL)中删除未使用的类型(类、结构等)。 即使您使用一个类型,UnityLinker 也会删除该类型未使用的方法。
注意: 虽然这个功能在使用 Mono 脚本后端的构建中是可选的,但是它总是在使用 IL2CPP 脚本后端的构建中启用。
2.Native code stripping
Unity 在播放机设置中默认启用条形码引擎代码,并启用本机代码剥离。 启用"条带引擎代码"以删除本机 Unity 引擎代码中未使用的模块和类。 禁用条形引擎代码以保留本机 Unity 引擎代码中的所有模块和类。
注意: 对于公开可用的平台,本地代码剥离只支持 iOS、 WebGL 和 Android。
Unity 2017.3以后支持 Android 上的本地代码剥离; 在以前的版本中,Unity Android 运行时作为预链接发布。 所以图书馆,Unity 不能剥离。 2017.3发布的 Android 运行时是一个静态引擎代码库,支持本地代码剥离。 最后一个链接发生在构建过程中,这也是构建时间稍长的原因

Unity Module Stripping
注意: WebGL 是目前唯一支持剥离未使用的 Unity 模块的平台。
Unity 尽最大努力消除所有未使用的 Unity 模块。 这意味着,如果任何场景使用或任何脚本引用了你在构建中包含的 Unity 模块中的一个组件,Unity 不会剥离该模块。 Unity 不会去掉核心模块,比如 Camera,AssetBundle,Halo 等,但是在将来的版本中,Unity 也会去掉这些模块。
从WebGL上的一个空项目中剥离模块
删除模块可以节省大量内存。 例如,Unity 中最大的模块之一是物理模块,它占用了约5mb 的带有 gzipped 的 ASM.js 代码。 如果您删除一个空项目的物理模块,它会将构建大小从17 MB 减少到12 MB。

C# Code Stripping
Unitylinker 使用基本的标记和清除原则,类似于垃圾收集器。 Unitylinker 生成包含在生成的每个程序集中的每种类型和方法的映射。 Unitylinker 将一些类型和方法标记为"根",然后 UnityLinker 遍历类型和方法之间的依赖关系图。
例如,如果一个类型的方法调用另一个类型的方法,那么 Unity Linker 将标记被调用的类型和正在使用的 methodas。 一旦 UnityLinker 标记了所有根的依赖项,系统就会重组程序集,省略未标记为使用的方法或整个类型。

1.场景、资源、程序集和资产包的根
如果 UnityLinker 的内部类在场景中使用过,或者从参考资料中的内容中使用过,它就会将它们标记为词根。 类似地,UnityLinker 将用户程序集中的所有类型和方法标记为根。
如果您直接在场景或资源中包含的资产中使用来自其他程序集的类型和方法,Unity 将它们标记为根。
使用 link.xml 文件将其他类型和方法标记为根。 如果您的项目使用 AssetBundles,那么也可以使用 buildplayeroption.asssetbundlemanifestpath 将其他类型和方法标记为根。

2.用户程序集
用户程序集是 Unity 从 Assets 文件夹中的松散代码生成的程序集。 Unity 将大部分 c # 代码放在 Assembly-CSharp。 而 Unity 将代码放在 / Assets / standard Assets / 或 / Assets / plugins / 中的 Assembly-CSharp-firstpass.dll 中,后者也被视为用户程序集。
如果有相当一部分代码库类型或方法未被使用,您可以通过将稳定代码迁移到预先构建的程序集中,并允许 UnityLinker 删除它们,从而节省一些二进制大小和构建时间。 使用程序集定义文件将稳定代码迁移到预生成的程序集中。
Generic Sharing
对于引用类型,IL2CPP 生成可以使用引用类型在泛型之间共享的实现(c + + 代码)。 然而,IL2CPP 不共享值类型,因为 IL2CPP 需要为每个类型分别生成代码。 这会导致代码大小增加。
一般来说,不应该有任何明显的性能差异,但这取决于特定的用例以及应该为什么进行优化。 类通常在堆上,而结构则在堆栈上(除了一些例外,例如协程)。 对于内存性能和使用而言,这很重要,而使用非引用类型会导致其他问题。 必须使用值类型复制函数参数以影响性能。 更多信息请看这篇博客文章。 但是要注意,Integer 或者 Enum 类型目前还没有被共享。

Assembly Definition Files
程序集定义文件允许您定义自定义托管程序集,并根据每个文件夹为它们分配用户脚本。
反过来,这会导致更快的迭代时间,因为 Unity 将只构建那些实际上受到脚本更改影响的程序集。
注意: 虽然多个程序集确实实现了模块化,但它们也增加了应用程序的二进制大小和运行时内存。 测试表明,可执行文件每个程序集最多可增长4kB。

Build Report
构建报告是一个包含在 Unity 中但是没有用户界面的 API。 构建一个项目会生成一个构建 / 挖掘文件,它可以让你发现什么被删除了,以及为什么从最终的可执行文件中删除了它。
要预览剥离信息:

  • 建立你的项目。
  • 打开编辑器。
  • 连接到 http://files.unity3d.com/build-report/ 。

构建报告工具连接到正在运行的 Unity 编辑器,下载并显示构建报告的分解。
可以在 library / latestbuild 生成的文件上使用 binary2text 工具。 可以查看报告中的数据。 Binary2text 在 Unity.app / contents / Tools / on Mac 或 Unity / editor / data / Tools / on Windows 下附带 Unity。 构建报告在 Unity 5.5及以后版本中可用。

Unity 托管内存(Managed Memory)相关推荐

  1. 一篇文章读懂Unity内存 Understanding Memory on iOS

    孙广东   2018.5.26 Understanding Memory on iOS - What kind of memory? • Physical/Resident Memory • Grap ...

  2. Unity 使用Marshal类将托管内存封送到非托管内存

    C++代码通常被称为非托管代码,而我们在Unity中使用的C#代码会被编译成通用中间语言CIL,CIL/.Net代码通常被称为托管代码.那我们如何在Unity中调用由C++封装的dll动态库中接口时将 ...

  3. Unity AssetBundle内存管理相关问题

    AssetBundle机制相关资料收集 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大. 这里写下关于Unity3D对于内存的管理与优化. Unity3D 里有两种动态加载机制:一个 ...

  4. 【Unity】内存泄漏危害及处理方式(腾讯WeTest分析使用)

    WeTest导读 本文通过对内存泄漏(what)及其危害性(why)的介绍,引出在Unity环境下定位和修复内存泄漏的方法和工具(how).最后提出了一些避免泄漏的方法与建议. 在之前推送的文章< ...

  5. C# 托管内存与非托管内存之间的转换

    C# 托管内存与非托管内存之间的转换 c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我 ...

  6. 转 C# 托管内存与非托管内存之间的转换

    1.c#的托管代码和非托管代码 c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作 ...

  7. .NET托管内存类应用的内存泄漏分析和诊断

    在托管内存管理中,"泄漏"意义不同与传统 Native 应用中的忘记显式释放(delete/delete[] 等)不同,当然对于非托管资源之类(如句柄等)还是需要在 Finaliz ...

  8. 一次.net托管内存泄露分析

    简介:一次.net托管内存泄露分析 最近协助分析了一个.net进程内存泄露的问题,过程分享给大家. 症状:客户的服务端.net进程出现分钟级的cpu抖动,接近100%后落回. 图1 分析:支持同学通过 ...

  9. .NET托管内存类应用的内存泄漏分析和诊断(转)

    在托管内存管理中,"泄漏"意义不同与传统 Native 应用中的忘记显式释放(delete/delete[] 等)不同,当然对于非托管资源之类(如句柄等)还是需要在 Finaliz ...

最新文章

  1. 告别痛苦,快乐学习Pandas!开源教程《Joyful-Pandas》发布
  2. ffmpeg Windows Error 0xe06d7363
  3. Vue实现仿音乐播放器4-Vue-router实现音乐导航菜单切换
  4. html5 获取文件属性,H5新属性--file文件读取
  5. PyCharm社区版支持深度学习_深度学习,大家都看哪些社区论坛?
  6. Python基本数据类型以及字符串
  7. 《Imperfect C++中文版》——1.3 运行期契约:前置条件、后置条件和不变式
  8. Oracle 4dae,如何处理Python-CXOracle中未知词的错误报告问题,pythoncxOracle,查询,到,生僻字,报错...
  9. Web开发技术大会演讲
  10. SVN学习2020.8.9
  11. 微软 Fluent 设计体系, Fluent UI
  12. 别嘲笑老同志了!网络诈骗,19岁小鲜肉最容易中招
  13. 对联广告html,Js对联广告代码示例(入门)
  14. 深入理解React:懒加载(lazy)实现原理
  15. 【python】pandas库pd.to_excel操作写入excel文件参数整理与实例
  16. Crontab中的除号(slash)到底怎么用?
  17. 企业战略 平台转型:不走寻常路
  18. 通过配置环境变量解锁win+r新玩法
  19. MSP430F5529 口袋板 实验板 资料 单片机 呼吸灯 音乐频谱 万年历 电子时钟 温度计 墨水屏 声控灯
  20. Nexys A7 上手历程 【流水灯】

热门文章

  1. 【源码阅读 | 04】update-notifier 检查包更新
  2. 基于51单片机数码管显示
  3. linux中错误无法解析域名无法下载,Linux无法解析域名的解决办法
  4. 木门工厂木门、门套、套线公式和算法
  5. 【题解】AtCoder ARC128D - Neq Neq
  6. R语言dbplyr包实现R与SQL语句无缝衔接
  7. 2018-2019 ICPC, NEERC, Northern Eurasia Finals K. King Kog's Reception 线段树
  8. 【Pandas】一文入门Pandas处理csv文件数据集(神经网络/机器学习算法数据预处理)
  9. git常用命令(持续更新)
  10. 微信小程序时间格式在IOS苹果手机上不识别