内存管理(一)

Q1:Texture占用内存总是双倍,这个是我们自己的问题,还是Unity引擎的机制?

出现这种情况的原因有两种:一种是你在真机运行时开启了Read&Write。另一种可能是Unity的Bug,目前的Unity 5.2.3 release note如下 :
(735644) - OpenGL: Fixed texture memory usage reporting in profiler, was twice the actual size for most textures.
开发者需要关注下自己的开发版本,5.2.3以前类似情况的项目可以参考一下。

Q2:我现在发现两个因素直接影响Overhead,一个是Shader的复杂度,一个是空Update方法及其同类空方法,不知道是否还有其他因素?

Overhead的计算方法是:Profiler当前帧统计的总耗时时间减去所有已知选项的累加时间,即引擎当前还无法识别模块的耗时时间。Overhead数值理论上是趋向于0的,但是由于目前市面上的硬件设备、系统框架过于丰富,所以引擎可能无法识别所有模块的CPU开销。
就目前遇到的大部分案例而言,Overhead数值较高一般是由硬件设备的垂直同步算法无法识别而引起的。所以,一般情况下,Overhead的数值其实并不需要开发者特别关注。
在UWA的性能分析中,我们并没有将Overhead计算在内,一方面是其本身数据的统计意义对目前大多数项目的性能优化帮助不大,另一方面是即便知道了它的CPU数值,也无法知道到底是哪些地方引起的,上层很难有针对性地进行优化。
当然,我们会持续对Overhead进行实验和研究,分析其CPU耗时规律、与已知选项的关联性等。

Q3:在Unity的内存管理机制中, Reserved Total 和 Used Total之间的关系是怎样的?

Reserved Total 和 Used Total为Unity引擎在内存方面的总体分配量和总体使用量。 一般来说,引擎在分配内存时并不是向操作系统 “即拿即用”,而是首先获取一定量的连续内存,然后供自己内部使用,待空余内存不够时,引擎才会向系统再次申请一定量的连续内存进行使用。所以,从图表中可以看到,Reserved Total 的内存占用量略大于 Used Total, 且两者走势基本一致。

内存管理(一)_第1张图片
Blog-TechSharing_1-1.jpg

注意:对于绝大多数平台而言,Reseved Total内存 = Reserved Unity内存 + GFX内存 + FMOD内存 + Mono内存

Q4:纹理Atlas是建议合成一张2048(尺寸)的纹理还是四张1024的纹理?

在其他设置一致的情况下,这两种方式无论在加载还是渲染方面其实并没有实质上的差别。在我们接触到的大多数案例中,纹理资源方面的问题除了尺寸外,纹理格式、Mipmap设置和Read&Write功能同样是需要研发团队时刻关注的。

Q5:如图,在Editor中查看Profiler里的内存详细信息,发现Used Total中有个“Unity”,请问是什么意思?为什么会特别大?

Blog-TechSharing_3-1.jpg

在Editor中运行时,“Unity”大是正常的,因为在Editor中运行项目时,引擎包含了所有的资源占用的内存(除了部分纹理和Mesh是在GFX中),同时自身会进行很多的辅助操作来记录各种游戏运行信息。一般来说,在查看游戏运行时的真实消耗内存,我们均是推荐直接在发布游戏上通过Profiler进行查看,在Editor中运行游戏所看到的内存是要大很多的。

Q6: 在进行内存优化时,Unity Profiler给出的数据和Android系统(adb dumpsys meminfo,已经考虑memtrack的影响 )的数据差距较大(已经分析了Profiler自身的内存占用),如何分析这部分差异,比如包括对显存消耗进行准确统计,OS消耗的统计等等?

内存差异较大是正常的,一般来说,Profiler统计的内存较为一致,而Android系统通过ADB反馈的PSS、Private Dirty等值则是差别很大。这主要是因为芯片和OS的不同而导致。具体的Android内存,建议直接查看Google Android OS的相关文档。
Unity Profiler反馈的则是引擎的真实物理使用内存,一般我们都建议通过Profiler来查看内存是否存在冗余、泄露等问题。

Q7:System.ExecutableAndDlls占内存巨大,且一直在增长,这个属于正常情况吗?

System.ExecutableAndDlls该项显示的是执行文件和所调用的库(物理、渲染、IO等系统库)的总和。开发团队不用太担心该选项的数值,因为很多应用均在共用这些库,并且它对于真实项目的内存压力非常小,几乎没有影响,而且OS也不会因为该内存而杀掉游戏或应用。

Q8:已经预加载怪物,然后显示怪物 PSS上升,并且在隐藏怪物后并没有下降,这是什么原因导致?显存上去了吗?

仅仅隐藏怪物的话,内存是不会下降的。因为隐藏只是改变了GameObject的状态,并没有对内存中的Object和资源进行移除。同时,即使是提前加载了怪物,也依然可能存在以上问题,因为某些资源是在显示的时候,才会传输一份到GPU的,比如Mesh。一般情况下,显存都不会即刻降低,这个是由Graphics Driver来管理的。建议可以看Profiler是否增长,如果Profiler没有问题而PSS持续增长,就有可能发生了内存泄露。
对于这个问题,建议查看性能优化,进无止境---内存篇(下)加深理解。

Q9:我们在美术制作时做了40根骨骼,但在动作中仅用到了其中的30根。这种做法和30根骨骼用到了30根相比,在蒙皮计算上会明显增加吗?(Animation经过了压缩处理)

理论上是有增加的,骨骼运算均是每个骨骼阶段的Matrix乘起来的,所以理论上会有开销。建议使用Optimize GameObejct选项,可以减少一些不必要的CPU开销。

Q10:不太明白Profiler中ManagedHeap.UsedSize是什么,以及这个参数的意义何在?是否重要?

ManagedHeap.UsedSize是项目逻辑代码在运行时申请的堆内存,该选项只能通过优化代码来进行降低。 优化方法一般如下:
1.尽可能地复用变量,减少new的次数;
2.使用StringBuilder代替String连接,使用for代替foreach;
3.对于局部变量或非常驻变量,尽可能使用Struct来代替Class。
ManagedHeap.UsedSize过大,一方面可能会影响一次GC的耗时;另一方面也可能反映出脚本中不合理的GC Alloc。

你可能感兴趣的:(内存管理(一))