02. 内存分析

作者: Wenchao | 来源:发表于2017-08-30 21:52 被阅读94次

    这是摘自Unity官方文档有关优化的部分,原文链接:https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity.html
    总共分为如下系列:

    1. 采样分析
    2. 内存部分
    3. 协程
    4. Asset审查
    5. 理解托管堆 【推荐阅读】
      5.1 上篇:原理,临时分配内存,集合和数组
      5.2 下篇:闭包,装箱,数组
    6. 字符串和文本
    7. 资源目录
    8. 通用的优化方案
    9. 一些特殊的优化方案

    内存消耗是关键的性能指标,尤其对于在内存资源非常有限的设备上,如移动设备。

    剖析内存消耗

    分析内存问题最好的工具是Unity在Bitbucket上开源的工具:
    https://bitbucket.org/Unity-Technologies/memoryprofiler
    只需要下载对应的代码仓库将其放到项目中的Editor目录下即可。

    注意,这个工具在Unity5.3之后的版本都可以使用,如果应用是用IL2CPP打包的,它可以提取原生代码和托管代码的内存消耗信息。

    使用这个工具,需要使用IL2CPP工具进行打包并且发布到合适的设备上,然后连接上编辑器中的CPU剖析工具,打开内存剖析界面(Window > MemoryProfilerWindow)选择Take Snapshot。

    设备上收集数据,并将这些数据发送给Unity编辑器,应用会暂停一段时间。然后Unity编辑器开始分析数据,这也需要比较久的时间。对于内存比较敏感的应用,这个过程可能需要10-30分钟完成。

    在解析数据和加载的过程中,建议各位耐心等待。

    image.png

    上面的截图来自于iOS设备上运行的标准Asset场景,显示了四分之三多的内存给了四个非常大的飞行器的机身纹理贴图。

    这个可视化的工具也可以被放大。点击每个方块可以获得更多的相关信息。

    定位重复的纹理

    最常见的内存问题是在内存中的资源重复。纹理是最占内存开销的资源类型,纹理重复是Unity项目中最常见的问题。

    如果两个对象是相同大小,相同类型,那么很有可能这两个对象是从同一个Asset加载进来的。在新的内存剖析器中,可以通过Name和InstanceID观察查看资源。

    Name是加载进来的Asset文件的名称,通常不带路径名和后缀。InstanceID是Unity采用的内部识别编号,在Unity运行的过程中,这个编号是独一无二的。

    image.png

    这张图示范了资源重复的一个例子。图形的左边和右边是从Unity5.4的内存剖析器中的某个细节面板。两张图的Asset实际上是内存中两个分开加载的纹理资源,名字和大小相同。可以在Assets目录下搜索资源名字,确认是否只有一个资源较这个名字,从而确定是不是资源重复加载。

    内存中每个独立的UnityEngine.Object都有独特的instance ID,当Object被创建的时候指定。这两个纹理有不同的Instance IDs,所以它们代表了两份不同的纹理数据。

    因为Asset的大小和名称相同,而InstanceID不同,所以可以确定一个纹理被加载了两次。虽然有可能会出现两个同名的资源文件,所以还是按照文件大小来判定。
    AssetBundle和Asset重复
    纹理资源和Asset重复的最大原因是AssetBundle的不合理使用。可以参见AssetBundle相关的知道。关键章节是管理已经加载的Asset。

    检查图片缓冲区,图片效果和RenderTexture内存使用

    同样也可以在剖析器中看到为图片效果和RenderTexture提供渲染缓冲区占用的内存大小。

    image.png

    上面的截图展示了使用了Unity电影图片效果的一个场景的内存剖析器的情况。这个图片效果分配了临时渲染缓冲区,而且Bloom效果分配了多个缓冲区。因为iOS设备的高分辨率,这些临时缓冲区占用了非常多的内存,比项目中剩下的占用的总数还多。

    考虑到iPad Air2的分辨率是2048x1536,比大部分终端设备和PC的1080p的分辨率高出了很多。全屏的临时渲染缓冲区差不多消耗24MB~36MB,取决于缓冲区的格式。降低渲染缓冲区的像素大小可以节省75%的内存消耗,同时也不会对最终的效果造成很大的影响。

    优化图片效果,减少临时缓冲区和其他的GPU资源的消耗另一个优化方法是创建单个“uber”图像效果一次执行所有不相干的计算。如果使用Unity5.5或者更新的版本,可以使用新的UberFX。
    参见资料:https://github.com/Unity-Technologies/PostProcessing
    这个例子提供了一个可以配置化的“uber”图片效果,可以执行Cinematic Image Effect的所有操作,相比普通的独立Image Effect可以节省不少资源。

    上篇:采样分析
    下篇:协程

    如果觉得文章对您有用,请点个赞呗!☺☺☺

    相关文章

      网友评论

        本文标题:02. 内存分析

        本文链接:https://www.haomeiwen.com/subject/jmxfjxtx.html