Native Memory

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

在优化应用程序时,Native Memory是一个关键部分,因为大多数引擎代码位于常驻内存中。 当你在原生插件中集成代码时,你可以直接控制它,但是从 Unity 内部系统中控制和优化Native Memory消耗并不总是可能的。 内部系统使用不同的缓冲区和资源,它可能并不总是明显地影响内存消耗。 下面的部分详细介绍了 Unity 内部系统,并解释了您在Native Profiler中经常看到的内存数据。

Native Buffer

Unity 使用许多不同的本地分配器和缓冲区。 有些是持久性的,如常量缓冲区,而其他则是动态的,如后台缓冲区。 下面的子节描述了缓冲区及其行为。

Scratchpad

Unity 将常量存储在一个4mb 的缓冲池中,并在帧之间的缓冲池中循环。 该池在其生命周期内与 GPU 绑定,并显示在帧捕获工具中,如 XCode 或 Snapdragon。
在这里插入图片描述

Block allocator

Unity 在一些内部系统中使用块分配器。 在 Unity 需要分配新的页面内存块时,会有内存和 CPU 开销。 通常,页面的块大小足够大,以至于分配仅在 Unity 第一次使用系统时才出现。 在第一次分配之后,页面块将被重用。 内部系统使用块分配器的方式有细微的差别。

AssetBundles

第一次加载 AssetBundle 时,当块分配器运行时,需要额外的 CPU 和内存开销,从而允许 Asset Bundle 系统分配第一个页面内存块。
但是,如果您想同时加载许多Asset Bundles,Unity 会重用Asset Bundles系统分配的页面,那么您可能必须分配第二个或第三个块。 所有这些停留分配,直到应用程序终止。

Resources

Resources使用一个与其他系统共享的块分配器,因此在第一次从Resources加载Asset时不会有 CPU 或内存开销(正如之前在启动时所发生的那样)。

Ringbuffer

Unity使用一个环形缓冲区将纹理推送到GPU。 你可以通过QualitySettings.asyncUploadBufferSize来调整这个异步纹理缓冲区。 注意:Unity分配了Ring 缓冲区内存后,您不能将它返回到系统。

Assets

在运行时,资产会引起本机和托管内存问题。 除了托管内存之外,Unity 在不再需要时将本机内存返回到操作系统。 由于每个字节都很重要——尤其是在移动设备上——你可以尝试以下方法来减少本地运行时内存:

  • 从网格中移除未使用的管道
  • 从动画中删除多余的关键帧
  • 在Quality Settings中使用 maxLOD 可以从构建中删除 LODGroups 中较高的细节网格
  • 在构建之后检查 Editor.log,以确保磁盘上每个 Asset 的大小与其运行时内存使用成正比
  • 通过使用质量设置渲染部分的纹理质量设置,通过 mipmap 强制降低纹理分辨率,从而减少上传到GPU内存的内存
  • 法线贴图不需要与漫反射贴图(1:1)大小相同,因此您可以对法线贴图使用较小的分辨率,同时仍然实现高视觉保真度并节省内存和磁盘空间

请注意,由于托管堆的大量碎片,托管内存影响通常会超过本机内存问题。

Cloned Materials

谨防克隆材料,因为访问任何渲染器的材料属性都会导致材料被克隆,即使没有分配任何内容。 这个克隆材料不会被垃圾回收,只有在您更改 Scenes 或调用 Resources.UnloadUnusedAssets ()时才会被清除。 如果想访问只读材料,可以使用 customer.sharedmaterial。

Unloading Scenes

调用 UnloadScene ()来销毁和卸载与场景相关的游戏对象。 注意: 这不会卸载相关联的资产。 为了卸载资产并释放托管内存和本机内存,需要在卸载场景后调用 Resources.UnloadUnusedAssets ()。

Audio

1. Virtual Voices
Unity 根据平台的实时可听性,动态地将声音设置为虚拟或真实。 例如,Unity 设置了远距离或者低音量的声音作为虚拟声音,但是如果声音靠近或者变大,它就会把这些声音变成真实的声音。 音频设置中的默认值是移动设备的很好的值。

Max Virtual Voice Count Max Real Voice Count
Default 512 32
Maximum 4095 255

2.DSP Buffer Size
Unity 使用 DSP 缓冲区大小来控制混频器的延迟。 底层音频系统 FMOD 定义了与平台相关的 DSP 缓冲区大小。 缓冲区大小影响延迟,应该谨慎处理。 缓冲区的数量默认为4。 在 Unity 中的音频系统使用以下样例计数来设置 Unity 中的音频设置:

Latency = Samples * Number of Buffers Samples Number of Buffers
Default iOS & Desktop: 1024 Android: 512 4
Best latency 256 4
Good latency 512 4
Best performance 1024 4
Audio Import Settings

使用正确的设置可以节省运行时内存和 CPU 性能。
1.如果音频文件不需要立体声,则启用Force to mono选项; 这样做将减少运行时内存和磁盘空间。 这主要用于带有单声道扬声器的移动平台。
2.更大的音频片应该设置为Streaming。 在 Unity 5.0及以后版本中的流媒体开销为200KB,因此您应该将小于200KB 的音频文件设置为Compressed into Memory。
3.只有在内存充足但 CPU 性能有限的情况下才使用 Decompress On Load,因为这个选项需要大量的内存
各种平台也有首选的压缩格式设置,以节省运行时内存和磁盘空间:
1.设置压缩格式为 ADPCM 的非常短的剪辑,如声音效果,经常播放。 Adpcm 提供了一个固定的3.5:1压缩比,并且是廉价的减压。
2.在安卓系统上使用 Vorbis 进行更长的剪辑。 统一不使用硬件加速解码。
3.在 iOS 上使用 MP3或 Vorbis 播放更长的视频剪辑。 统一不使用硬件加速解码。
Mp3或 Vorbis 需要更多的解压资源,但提供更小的文件大小明显。 高质量的 mp3需要较少的解压缩资源,而中等质量和低质量的文件需要几乎相同的 CPU 时间进行解压缩。
提示: 使用 Vorbis 作为更长的循环声音,因为它处理循环更好。 Mp3包含预定大小的数据块,因此如果循环不是块大小的精确倍数,那么 MP3编码将增加沉默而 Vorbis 不。

Android Memory Management