详解Unity Profiler内存分析问题
在Unity的Profiler中看到的总内存使用和我使用其它工具看到的系统内存占用不太一样,这是为什么呢?
Profiler中看到的内存是通过Unity自身引擎的内存分配,凡是引擎分配和释放的内存,引擎均有记录,所以我们可以给出确切的引擎内存占用信息。但是,仍有其他内存我们是无法获知的。
而Unity Profiler记录的则是目前真实使用的物理内存,即上述所说的第一部分。因此,当游戏运行时间越长,Profiler分配内存和通过其他软件获得的系统内存差距会越大。
因此,只要所使用的第三方库不存在内存泄露问题,我们一般都建议只需要查看Profiler即可,只要Profiler中的内存可以保证正常升高和回落,那么引擎这边分配的内存就是没有问题的。
我们做项目的时候发现有时Profiler中System.ExecutableAndDlls这项占用很多,有什么解决办法吗?
“System.ExecutableAndDlls”该项显示的是执行文件和所调用的库(物理、渲染、IO等系统库)的总和。请不用担心该选项的数值,因为很多Application均在共用这些库,并且它对于真实游戏的内存压力非常小,而且也不会导致系统因为该内存来Kill掉游戏。
为什么在Profiler中的Simple模式下,Used Total的数值不等于其右边各项Unity, Mono, GfxDriver, FMOD与Profiler总和呢?
其实在Unity中,Used Total的计算公式为Used Total = Unity + Mono + GfxDriver + Profiler + additionalUsedMemory。公式中的additionalUsedMemory项在Profiler中并没有显示,因为这一项一般情况下都为0,只在某些特殊发布平台下才会有数值(一般Android,PC和IOS都为0)。因此一般情况下Used Total的值就是除FMOD之外各项的总和了。当然,这个规则对于Reserved Total是同样适用的。
我们项目的资源主要使用AssetBundle动态加载资源,发现Profiler中Detailed模式下PersistentManager.Remapper一项占用时多时少,这一项主要是做什么的呢?
Remapper主要提供文件的持久化存储,包括各种序列化的Asset,项目的设置文件等,维护文件系统的中的文件与内存中数据的对应关系。
那么如果项目大量使用AssetBundle的话,在对AssetBundle进行Unload之前都会需要占用Remapper的内存的。而Remapper本身的实现使用内存池,其数值只会增大,那么为了使Remapper占用的内存保持在一个稳定的数值上,我们需要每次在加载一定数量的AssetBundle之后进行Unload操作,而不要一次性把所有AssetBundle都加载后才调用Unload。(这样的操作对维持整个Mono Heap的大小也是至关重要的,因为Mono Heap本身也是只增大不减小的。)
我们在Editor中调试项目的时候发现纹理的内存大小是其本身大小的两倍,是因为Unity把内存和显存的大小都计算进去了吗?其实并不是这个原因,因为Editor本身会保有纹理的一份内存,在Editor下进行Profiler会把Editor本身所使用的纹理大小也计算进去,因此会有内存变为两倍的情况。我们官方并不建议在Editor下对项目进行性能调试,而是务必要在真机上跑编译好的项目,然后连接Profiler进行调试,只有这样才能得到真正精确的测试数据。
总结:一般情况下只需Unity Profiler在手,就能窥测到游戏中各项内存使用状况,当然前提是需要对Profiler各项数据所表达的含义了然于心。并且尽量使用真机调试结合Profiler,这样才能了解到游戏运行的真实内存占用数据。
关于Profiler内存分析相关的问题先分享到这里,如果你有什么其它迫切希望了解的问题也可在文末评论区留言来告诉我们。
我们还会分享更多相关的内容在Unity官方中文社区(forum.china.unity3d.com),敬请保持关注!