前端性能测试

导读

目前游戏行业已经呈现精品化状态,行业对测试岗位的要求也越来越高,前端性能测试仅仅是用工具测试出相关数据(自动化测试即可满足,包括自动化脚本,或者自动化录像),并告知研发,已经不能满足测试要求。所以性能测试岗同学需要具备更多硬性技能,本篇文章适合性能测试新手;分别从测试场景,测试工具,然后测试数据概念,之后到和开发、美术同学在优化中的沟通,以及最后常用的优化方法策略,逐一展开介绍。

一、测试场景

1.导读

前端性能测试,关注用户在玩游戏过程中的性能方面的体验,包括是否卡顿,是否 crash,是否手机发热,是否耗电过快等,不管用户的手机是高配机,中配机器,还是很渣的低配机器,都需要关注用户性能体验(有同学问,为什么还这么关注低配机用户的感受,他们能充钱吗?游戏是一个生态,比如 5% 的 RMB 用户需要剩余 95% 的屌丝用户来衬托;另外游戏口碑等都需要考虑所有用户的体验等)。

2.卡顿

游戏流畅是游戏比较基本的性能指标,尤其在核心玩法的时候。从测试角度看,更多关注游戏的 fps 数据、卡帧率、bigjank 值等

3.crash

用户不希望游戏过程中出现 crash 情况,测试关注 crash 率数据

4.发热

手机发热之后除了体感不好,另外不同的手机厂商会选择降频或者锁核,从而导致游戏卡顿。手机发热原因较多(比如运行高功耗 app、在充电中、不良电池、保护壳不能散热、所处环境温度高等),这里关注的是怎么降低游戏的功耗,其实更多是怎么降低 GPU 和 CPU 的使用率

耗电过快

手机电池毫安数本身就是手机的重要指标,耗电快无疑是硬伤。

二、测试工具介绍

1.perfdog

腾讯出品的性能工具,无需 root 或者越狱。PerfDog 支持移动平台所有应用程序(游戏、APP 应用、浏览器、小程序、小游戏、H5、后台系统进程等)
安装,使用教程等参考官网详细介绍:
https://bbs.perfdog.qq.com/article-detail.html?id=5

2.UWA

针对 unity 和 unreal 引擎的游戏或者 VR 产品提供服务,包括资源监测(动态和静态,免费),性能诊断和优化(收费),lua 性能分析,自动化测试,社区问答等
UWA GOT 是 UWA 推出的本地性能测评工具,需要装对应 sdk,无需越狱或者 root。
UWA 成立 2015 年,目前积累了不少用户和测试数据,是目前比较主流的测试工具和社区。
安装和使用,官网详细介绍:
https://uwa-public.oss-cn-beijing.aliyuncs.com/uwa-got/document/UWA%20GOT%20%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.pdf

3.UPR

UPR 开始于这两年(2019 开始,wetest 的性能之前和 untiy 配合,后来 wetest 自研了 Perfdog,游戏性能移交给 unity 自己做了),目前 UPR 在积累用户中,所以是免费的,而且技术支持比较好(有什么问题反馈比较及时,甚至会现场解决),UPR 的一些功能还在完善和开发中
URP 分手机和桌面版,可以带 sdk 和不带 sdk,当然,没有继承 UPR sdk 的测试数据会少。
安装和使用,参考官网介绍:
https://upr.unity.cn/instructions

4.其他测试工具

比如腾讯 GT,网易的 Emmagee,以及 google 的工具等等

5.自研测试工具

对应一些厂商,比如调用引擎给的接口等方法,来获取相关性能数据,来实现工具的目的。

三、测试数据概念介绍

1.内存

一般关注:
①pss 内存(实际使用的物理内存)的大小(ios 和 andriod 机器一般都是分三档机器,每档机器的 pss 内存标准不一样,标准数值随着硬件设备提升也在逐渐而变高)
②内存泄漏(内存泄漏后,内存越来越大,可能会因为申请分配内存越来越慢导致的卡顿,或者 crash 等)
③内存资源重复率:资源重复是指内存中同一时刻,存在两份或以上相同的纹理、网格、动画、音频等资源。一般是相同的一份资源被打包到多个 AB 包中,如果这些 AB 都被加载进内存,内存中就会存在多份相同的资源

2.bigjank

PerfDog 计算方法:同时满足两条件,则认为是一次卡顿 Jank.
1、 当前帧耗时>前三帧平均耗时 2 倍。
2、 当前帧耗时>两帧电影帧耗时 (1000ms/24*2=84ms)。
同时满足两条件,则认为是一次严重卡顿 BigJank.
1、 当前帧耗时>前三帧平均耗时 2 倍。
2、 当前帧耗时>三帧电影帧耗时 (1000ms/24*3=125ms)。

3.FPS

帧率,标准要求比如:核心游戏场景默认要求 90% 数值都不低于 25FPS;

流畅度

比如:核心游戏场景,默认要求卡顿率不高于 2%

4.CPU

比如:综合 CPU 平均占用 (90%) 小于 60%,单核 CPU 峰值占用(90%)小于 90%
另外要关注单核 CPU 使用率,以及是否所有内核都在使用,以及使用是否平均等
还有 CPU 的曲线是相对平滑,还是锯齿严重

5.工具中常用数据

cpu:
①frameTime:同一帧的耗时
②Rendering Time:当前帧渲染耗时;drawcall 越高,这部分开销越大
③ScriptTime:当前帧函数耗时
④PhysicsTime:当前帧物理耗时
内存:
代码中的内存 –Mono 内存(mono 内存,内存池,只增不减);资源中的内存占用 –Native 内存
①ReservedMono:一般是脚本分配的内存
②pss 内存:一般用于定位多局战斗、场景跳转、打开关闭 UI 中是否有内存泄漏
③total_reserved 内存:unity_reserved 内存 +GFX 内存 +FMOD 内存 +Mono 内存 +Profiler 内存
④mono reserved:分配的 mono 内存(绿线部分),只升不降,需要严格控制。mono 内存表示游戏中脚本分配的内存
⑤gfxdriver_reserved:表示渲染模块的内存,如果比较高需要对纹理资源和 Shader 进行优化。
⑥fmod_reserved:表示音频模块的内存,如果比较高需要对音频资源进行优化
⑦内存资源重复率:资源重复是指内存中同一时刻,存在两份或以上相同的纹理、网格、动画、音频等资源。一般是相同的一份资源被打包到多个 AB 包中,如果这些 AB 都被加载进内存,内存中就会存在多份相同的资源

其他数据可以参考:
https://segmentfault.com/a/1190000016342638?utm_source=tag-newest

四、研发(开发和美术)概念介绍

1.导读

在和研发同学沟通时,需要对研发上的一些概念,以及常用的优化思路,方法有所了解,可以根据问题数据,提供一些优化建议。

2.图集 atlas

是通过专门的工具,将多张图片合并成一张大图,并通过 plist 等格式的文件索引的资源
NGUI 强调图集,图集要规划好,否则经常会出现图集不够用等问题;UGUI 弱化用户对图集的概念,在打包的时候自动生成图集。各有优缺点
目前研发团队中主要使用的则是 Unity 自身的 UGUI 系统 和 Asset Store 上的 NGUI 插件

3.画布 canvas

Canvas 画布是承载所有 UI 元素的区域。Canvas 实际上是一个游戏对象上绑定了 Canvas 组件。所有的 UI 元素都必须是 Canvas 的自对象。如果场景中没有画布,那么我们创建任何一个 UI 元素,都会自动创建画布,并且将新元素置于其下

4.Collider

碰撞体

5.网格 mesh

mesh 就是我们所说的三角网格。三角网格就是由一系列三角形组成的多边形网格,主要用于模拟复杂物体的表面,事实上游戏开发过程中美术给我们的人体、车辆模型都是由一个或多个三角网络 (mesh) 组成的。
工具:mash baker,能够有效合并网格以及网格所使用的材质,来有效减少渲染批次所带来的开销

6.纹理 Texture

纹理即 “纹路”,每个物体表面上不同的样子,譬如说木头的木纹状。纹理就是一段有规律、可重复的图像

7.贴图 Map

贴图是图,最简单的形式是 ps 之类的软件做出来的一张图,这些图在 3D 中用来贴到物体的表面,用来表现物体的 “纹理”
最有名的是 lighting map,即光照贴图, 光照贴图是生成或者绘制出来,用于物体表面模拟光照效果的

8.材质 Material

材质主要是用来表现物体对光的交互(反射、折射等)性质的。譬如金属对光的反射和毛毯对光的反射性质完全不一样,那么对 3D 程序来说,这样的差别就通过材质这个属性来计算出不同的颜色。
材质,本质是数据集:表现物体对光的交互,供渲染器读取的数据,包括贴图,纹理,光照算法等

9.着色器 shader

实际上就是一小段程序,它负责将输入的 Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出,模拟真实世界中的光影效果,这个效果是由物体表面材质、灯光、观察者的视角等多种因素共同决定的
Unity 中所有的渲染都使用着色器完成

10.材质球

U3D 引擎中材质的预览方式为一个球体,材质球是什么样子,通常由贴图决定
纹理 --- 贴图--->经过 shader---->材质球--->材质球贴到具体的模型上,生成模型 1,模型 2......

11.Alpha 通道

指一张图片的透明和半透明度
对于 16bit 存储的位图,每 5 个 bit 分别表示红黄蓝,最后一个 bit 是表示阿尔法通道,0 或 1,所以要么透明要么不透明;对于 32 位存储的位图,每 8 个 bit 分别表示红黄蓝,最后 8 位表示阿尔法通道,就有 256 种透明可能

12.draw call

简称 DC,由 CPU 收集美术的资源信息,传递给 GPU,通知 GPU 进行一次渲染过程叫 DrawCall。是 cpu 通知 gpu 干活的一种命令

提交大量很小的 Draw Call 会造成 CPU 的性能瓶颈,即 CPU 把时间都花费在准备 Draw Call 的工作上了。把很多小的 Draw Call 合并成一个大的 Draw Call,这就是批处理的思想。

13.渲染通道 pass

每个 pass 都会消耗一个 drawcall,在满足渲染效果的情况下,尽可能减少渲染通道的数量

14.Lightmap

其实就是打了灯光的贴图,通常是对游戏场景中静态物体上,贴了一层带灯光效果的贴图
优点:省去了很大光照相关的计算,减少了性能的消耗
缺点:多了一层纹理,我们使用了灯光贴图肯定多了一层纹理。另外静态贴图无法改变灯光的方向,比如灯泡被用户打碎了,灯光效果还在,实际要干掉

15.mipmap

也是贴图。使用 Mipmap 后,贴图会根据摄像机距离的远近,选择使用不同精度的贴图
Mipmap 技术有点类似于 LOD 技术,但是不同的是,LOD 针对的是模型资源,而 Mipmap 针对的纹理贴图资源
缺点:会占用内存,因为 mipmap 会根据摄像机远近不同而生成对应的八个贴图,所以必然占内存!
优点:会优化显存带宽,用来减少渲染,因为可以根据实际情况,会选择适合的贴图来渲染

16.LOD

在游戏场景中,根据摄像机与模型的距离,来决定显示哪一个模型,一般距离近的时候显示高精度多细节模型,距离远的时候显示低精度低细节模型。
优点:可根据距离动态地选择渲染不同细节的模型,从而提高渲染的效率
缺点:加重美工的负担,要准备不同细节的同一模型,同样的会稍微增加游戏的容量

17.烘焙

物体表面的反光或者阴影,记录到模型里,形成新的贴图,运行的时候,显卡和 CPU 不需要进行对环境光效果的运算了。实际上就是 lightmap 的生成过程

18.面数 Tris

模型上的三角形面数,对应不同类型的模型,一般有不同的标准,比如小怪多少面,精英怪多少面,boss 多少面,随着游戏制作精度和硬件的提高,面数的标准也随着变多

19.bloom

Bloom 放在后期特效中,是实现光线绽放,灯光溢出的效果
特效有有 2 个最常见的后期:Color Grading(调色)和 Bloom(泛光/辉光)
参考链接:
https://zhuanlan.zhihu.com/p/76505536

20.GC

垃圾回收,一种内存管理机制(针对堆内存)
参考链接:
https://www.jianshu.com/p/db449e84a7ab

21.AssetBundle

资源打包,简称 AB 包,主要考虑打包策略和加载策略,比如:把需要同时加载的 Asset 尽量打包到同一个 AB 里。例如模型,其纹理和动画
参考链接:
https://zhuanlan.zhihu.com/p/91926428

22.渲染技术汇总

https://blog.csdn.net/poem_qianmo/article/details/78309500

五、开发优化工具介绍

不同的项目组,有不同的优化工具,也有共用的。

1.常见的共用优化工具

Unity Profiler,Unity Memory Profiler, XCode Instrument. XCode Instrument 内又包含了很多工具,其中最常用的有 Time Profiler,Allocation 以及 Capture GPU Frame。adb 命令
比如:XCode Allocation,会统计内存的分配和释放情况,从而看出是否存在内存泄漏情况(比如主城 -- 战斗 -- 主城,内存快照的情况下)

自研优化工具

比如:场景优化时:按照格子(比如 4 米 *4 米)获取场景内的热点数据;比如按照场景摄像机内的物件个数和物件类别的比例曲线,比如场景中,重复材质检查工具等

六、常用的优化方法策略

1.导读

①性能优化是一个长期的过程
②性能优化不但是程序部门的事情,而是需整个项目组共同配合和努力的结果,一般项目组每个部门都会有对应的专职人员
③好的优化工具至关重要
④不同的机器设备,展示的美术品质是不一样的,所以针对机型(分三档机器)有不同的优化策略
⑤每个核都充分利用,多线程渲染技术(unity5 以上就开始支持了)
⑥在不同的场景,时间和空间的选择(时间换空间,还是空间换时间,CPU 和 GPU 可以互换,CPU 和内存可以互换、内存和磁盘可以互换)
⑦不必要渲染的东西不渲染(比如 UI 层级,不显示的 UI 不渲染;不在摄像机内的不渲染;遮挡减少渲染;imposter,LOD,minimap 等)。不必加载的内容不加载(比如大表拆分按需加载;图集拆分按需加载等;AB 包加载策略等)。能压缩的都压缩(这个好理解)
⑧性能优化不是一劳永逸的事情,是持久战;即便是已经上线多年的长线产品,性能测试也是一如既往在挖掘性能点并优化
参考:
https://segmentfault.com/a/1190000019844821?utm_source=tag-newest

2.场景优化

①关注场景的热点数据(比如按照 2 米一个计算范围单位),通过调整物件的位置,优化物件的资源等来优化热点问题
②添加关键遮挡物,来减少相机内的渲染量
③LOD 技术的运用,或者 imposter 技术的运用等
④远景物件包括角色怪物等平滑渲染(多帧完成渲染)
等等(方法还有很多)

3.同屏人数优化

①同屏人主要集中的场景点,第一是要场景分离,比如拍卖行和交易地点分开,一个室内,一个室外;第二是减少对应场景的物件消耗
②计算策略优化,优先渲染离自己近的角色和场景物件
②效果优化,比如同一类型的特效到一定数量后不在渲染等
④同屏时用户角色是动态的,不停的加载和释放,做平滑处理(按帧控制渲染数目方法等)。避免瞬间加载导致的卡顿
⑤同屏战斗时,尤其国战,同角色 avatar 一样
⑥Imposter(伪装者,或者叫替代物) 技术:(基本原理用相机把模型各个角度的图片拍下来,然后根据玩家相机的角度选取不同的图片显示)
等等(方法还有很多)

4.UI 优化

比如:
①格式
②尽可能将动态 UI 元素和静态 UI 元素分离到不同的 UIPanel 中(UI 的重建以 UIPanel 为单位),从而尽可能将因为变动的 UI 元素引起的重构控制在较小的范围内
③带通道和不带通道图集,尽量分开
④同一个 UI 界面或者同一个功能点的 ui 资源放在一个图集,可以减少 drawcall
等等(方法还有很多)
参考:
https://www.cnblogs.com/wetest/p/6147011.html

5.GC 优化

GC 的时候会占用大量计算资源,如果 GC 之后发现内存依然不够用,需要再次分配(unity 非官方数据一次大概 6MB),那么就更耗资源了。GC 优化一般有:
①对象池技术 --- 重复使用对象(比如子弹,需要频繁的生成和销毁)
②减少内存垃圾的数量(比如:不要在频繁调用的函数中反复进行堆内存分配,后者使用缓存技术)
③减缓 GC 的时间,不要在关键时候 GC 操作;在非敏感期主动 gc
④其他技术手段,比如装箱,list,字符串等导致 GC 的解决方案
等等(方法还有很多)
参考:
https://www.cnblogs.com/u3ddjw/p/8624438.html

6.内存优化

内存性能原因主要有这几点:内存碎片过多(内存池解决)、内存频繁创建销毁(对象池解决)、内存加载慢、内存占用过高。
①资源(贴图,模型,动画,声音等)有损压缩,每种资源都有最优的压缩方式和格式等。
②脚本和配置,及时卸载,以及拆分等
③第三方 shader 库,冗余预编译宏占用
④AB 包打包策略和加载策略,都会影响内存占用。AB 自动打包工具(公共包合并,AB 包要在 10MB 内),游戏类型逻辑强关联打包模式,比如 moba,把一个英雄的所有资源打到一个包里。
比如:
第三方库内存占用,延时加载和模块隔离方法(第三方库内存泄漏,或者占用过大,方便处理)
比如技能表,常驻优化方案
去掉内存中同时存在的相同资源(比如特效资源)

Unity 资源内存优化,资源内存占用排行榜 (优化性价比):贴图>动画>网格>音频>材质
一、贴图优化
1.降低分辨率
2.拆分透明通道
3.调整压缩格式(比如带阿尔法通道的贴图拆分 2 两张,分别压缩;格式转换大概是原来 1/4 的内存)
4.禁用 Mipmap
5.启用 Use Crunch Compression
1 张 512*512 位图,安卓:RGBA ETC2(带通道)占用 256KB,RGB ETC2(不带通道)占用 128KB 内存;在 iOS:RGBA PVRTC(带通道)和 RGB PVRTC 都占用 128KB 内存
二、动画优化
1.减小动画长度
2.减少骨骼数量
3.减少关键帧密度
4.减少动画精度
三、网格优化
1.减少顶点
2.开启 Optimize Mesh 选项
四、音频优化
建议较长的音频使用.mp3 或.ogg 格式,较短的音频使用.wav 或.aiff 格式

7.CPU 优化

方法:
微观方法:从每一帧中发现问题(主要方法)
宏观方法:从统计中发现问题,比如一局战斗,每个模块和函数的耗时和调用次数统计,也方便不同版本的对比(工具或者日志来统计)
分类:
①GC,GCAlloc 耗时
②渲染耗时(合并批处理,减少 drawcall:比如使用动、静态批处理,GPU Instance 技术)
③逻辑耗时(比如循环查找,比如大量服务器消息集中处理等)
④其他引擎消耗(动画,物理)
参考:
https://gameinstitute.qq.com/community/detail/120536

8.GPU 优化

GPU 的计算目前看,大部分还是能胜任,设置错错有余的。所有在 CPU 优化方案里,有一部分就是把 CPU 做的事情,让 GPU 做。
GPU 优化思路:
①减少渲染批次
②同一个 drawcall 里,减少渲染类型
③平滑渲染

9.细节点

①模型尽量不要做成多个物体挂点组合的方式,如果多个物体用到不一样的材质,那额外产生的 DC 可是很酸爽的
②如果模型是带动作的话,模型的顶点数和骨骼数也是模型动作制作时的重要标准。
③图片占用内存的大小与图片大小、颜色深度、图片格式有关,与美术是否对图片资源进行压缩无关(android 用 ETC1,ios 用 pvrtc,不带 alpha 通道图片可以用 jpg)

10.性能监控

①内部监控(上传资源时性能监控,和版本测试时,性能监控;从而及时发现问题)
②外网性能监控,比如 wetest APM 监控系统。

12.耗电相关

工具:比如 google 的 Battery Historian
优化思路:
①计算优化。算法、for 循环优化、Switch..case 替代 if..else、避开浮点运算
②避免 Wake Lock 使用不当
③使用 Job Scheduler 管理后台任务
④降低亮度等

七、总结

手游性能测试的核心竞争力,更多是设计合理的测试用例,在测试完毕后分析数据,并根据问题数据提供合理化的优化建议;从而给研发团队提供高效服务,体现价值。


↙↙↙阅读原文可查看相关链接,并与作者交流