帕维尔·布斯科(Pavel Busko)2021年3月9日
《战车世界》(WoT)《闪电战》是一款基于会话的坦克射击游戏,自发布以来的过去7年中,MS-1(战争游戏最古老,规模最大的移动工作室)一直在不断对其进行更新。2014年,该游戏在iOS和Android上启动;几年后,它在桌面平台(Windows和macOS)上发布,Wot Blitz于2020年在Nintendo Switch上首次亮相。Android和iOS仍然是我们的主要平台,在这里应该指出的是,我们致力于使Blitz在性能方面具有可扩展性。从超低端移动设备到最新的旗舰产品。
性能对于每款游戏都至关重要。我们由独立,跨学科团队工作的将近200人的开发团队每年都会发布大约10个主要更新。为了跟上这种节奏和规模,我们必须自动化许多流程,性能测试也不例外。该博客探讨了如何使用持续集成(CI)测试来帮助我们为WoT Blitz带来最佳的玩家体验。我们还将深入探讨以下主题:
- 自动化性能测试方法论概述
- CPU分析
- Arm Mobile Studio和Performance Advisor在我们工作流程中的角色
WoT Blitz性能测试概述
如果我们将游戏大厅放在一边,仅考虑实际的游戏玩法(战场),则性能测试将包括对以下指标的控制:
- 进程使用的内存
- 地图加载时间
- 影格时间
对于主线构建,每晚都会触发自动测试。质量检查工程师在验证包含以下内容之一的变更集时也会触发这些测试:
- 内容变更
- 代码更改可能会影响性能
我们使用CI服务器运行测试,其中测试设备充当构建代理的角色。我们的测试服务器场由30多种设备组成,这些设备代表了所有受支持的平台和整个性能水平范围。
我们会尽力在问题进入主线之前发现问题,但是如果发生这种情况,每晚进行的回归测试就会显示出来。由于我们拥有大量的内容和大量的设备型号,因此我们制作了一个特殊的仪表板来显示所有夜间测试结果。以下是用于地图加载时间测试的该仪表板的一部分状态(完整版本具有13列和30行)。
根据我们的开发节奏和规模,拥有一个健康的主线至关重要:由于我们坚持尽早集成的原则,并且在为测试进行组装而构建时,功能分支总是与主线合并,因此主线中的问题可能是解释为功能分支问题。因此,我们对解决主线中存在的问题有严格的规定:导致问题的功能必须在一个工作日内被禁用或恢复。
考虑到我们有多少内容,以及我们支持多少平台和性能级别,如果没有自动化性能测试,很难想象我们的开发:
- 1.如果我们必须手动运行由自动化流程每晚触发的所有测试,则必须为此分配2或3名全职员工。但是更有可能的是,我们将损害设备或内容的覆盖范围或回归测试的频率,这会对开发速度产生负面影响。
- 2.测试需要性能测试的新内容和功能将比今天花费10-20%的时间。另外,由于手动性能测试的可靠性较差,因此更多问题会潜入主线。
报告中需要详细数据
如上所述,对于我们来说,在一个工作日内解决主线问题至关重要。但是,由于我们拥有许多独立和专业的团队,因此我们首先必须找出哪个人负责该问题。尽管测试是每晚进行的,但随着我们的开发规模的扩大,每天会有10-15个不重要的PR合并到主线中。而且,仅通过查看代码就无法始终了解是哪个问题导致了问题。这就是为什么我们希望自动测试报告尽可能详细地了解导致指标发生变化的确切原因。
除了定义哪个团队负责解决主线中的问题外,报告中的额外数据对于功能测试也非常有用。看到报告中的详细数据(例如,现在需要花费更长的时间才能执行该功能),程序员甚至可以在无需手动分析游戏的情况下找到问题所在。同样,有权访问此类数据的内容制作者也可以立即了解在何处寻求优化。
例如,对于内存测试,我们对Memory Profiler使用了特殊的构建。这可以将使用的整个内存池划分为“类别”(其中几乎有30种),而不仅仅是看到一个值的变化(某个进程的整体内存使用情况),还可以看到更详细的屏幕截图:
对于地图加载时间测试,报告仅包含一个数字(加载时间):
但是如果出现问题,您可以在测试工件中找到带有探查器跟踪的json:
要通过增加地图加载时间来整理所有内容,只需下载两次测试运行的json文件并使用chrome:// tracing进行比较即可。
对于FPS测试,我们花了很多时间思考一种方便的方式来在报告中显示详细信息。但是在显示结果之前,我们将介绍一些有关此类测试的一般方法。
好处
- 测试非常接近玩家的观察:在重播过程中,发生了各种游戏事件,所有图形元素(UI,粒子)的显示数量与实际游戏中的情况相同。
- 新地图的测试很容易获得:没有脚本阶段,您只需要进行游戏测试。当然,您不能将这样的测试称为对竞技场内容的完整测试:您只能检查一个特定玩家在游戏测试过程中所走的路线。但是要检查内容,我们进行了单独的测试,因此将相机放置在8x8网格的点上,每个点以45度的增量完全旋转。
缺点
- 测试需要花费大量时间。一张地图会在大约4分钟内处理完毕,如果我们将其乘以地图数(30),则为2个小时。
- 在重播中,游戏状态会非常动态地变化,有时很难将短暂的FPS下降与重播的具体部分相关联。
CPU Profiler如何增强FPS测试报告
长期以来,我们在报告中观察到的唯一结果就是平均FPS值。此外,在测试运行工件中,您可以找到重播期间FPS值的详细图表,其中点表示一秒钟长间隔的平均FPS值。后者是一个错误,因为单个长帧正处于雷达之下。当我们意识到这一点时,我们决定不测量每一帧的持续时间,而是走得更远并打开内部CPU Profiler进行测试。我们必须限制每个帧的计数器数量,以便探查器不会影响低端设备上的帧时间。为此,我们添加了标记功能:代码中的每个计数器都被标记了,我们可以打开或关闭标记组。默认情况下,启动自动测试时,每帧不超过70个计数器。
在自动测试中打开事件探查器会打开一个新机会:为各个功能的工作时间设置预算。这使您可以跟踪某些系统的性能峰值。除此之外,通过预算,可以更轻松地做出有关将新系统引入游戏的决策。例如,当几年前我们决定在战斗中添加UI控件的自动布局时,我们只是确保它不会影响测试中的FPS值。引入探查器后,我们有时会花多少时间在自动布局上感到非常惊讶。正确的方法是在添加新系统之前先定义预算。例如,
重放结束时,我们分析探查器跟踪,并将仅包含具有超出预算功能的帧的json放入工件中。在下面的示例中,列出了几十个帧。在其中每个场景中,Scene :: Update函数执行所需的时间均超过其应有的时间。
尖峰使一切都相对简单,但是哪种表示方法可以使注意到某些函数的执行时间略有增加变得简单呢?比较两个四分钟长的迹线似乎是不可接受的选择,因此我们决定从一些统计数据开始。对于一小部分最有趣的函数,我们计算函数执行时间达到一定范围内的帧数,从而获得频率分布:
接下来,我们将此数据发送到bigquery中,并使用Data Studio对其进行可视化:
在上面的图表上,您可以看到9月27日执行Engine :: OnFrame花费24-28 ms的帧数显着增加。要找到原因,我们可以使用一个简单的序列:
- 将呼叫堆栈下移一级
- 从具有仪表板筛选器的此调用堆栈级别中依次选择功能,直到找到导致问题的功能为止
- 如果我们还没有处于最低水平,请转到步骤1
如果我们已经达到最低级别并找到了“有罪”功能,那就很好了。但是,如果每个函数的执行时间或多或少均匀地增加,该怎么办?可能有几个原因:
- 热节流的可能性很大,这是在移动设备上进行性能测试的最大难题之一。我们通过将测试设备场放置在冷藏室中解决了这个问题。尽管我们为测试创建了一些不切实际的条件,但我们使大多数设备上的结果保持稳定。
- 一个新的线程出现了,它与我们的代码争夺CPU时间。可以通过采样分析器进行识别。
尽管在测试中引入仪器CPU探查器并不能排除使用采样探查器的必要性,但是它减少了需要采样探查器的情况。上面描述了一种情况,另一种情况是微优化,当您需要查看汇编代码中单独指令的执行时间时。
让我们回到“ 9月27日”问题。应用上面列出的一系列操作,我们发现该rhi::DevicePresent功能是应受的。此函数仅调用缓冲区交换,因此瓶颈必须在GPU端。但是,我们如何从报告中了解导致GPU处理帧时间更长的原因?
GPU指标
细心的读者可能会注意到,数据工作室屏幕快照中先前过滤器中的值之一看起来不像函数名称:“ DrawCallCount”。我们有更多类似的指标:“ PrimitiveCount”,“ TriangleCount”,“ VertexCount”。las,这是我们唯一可在CPU端收集的数据,以找出导致GPU端变慢的原因。但是,要解决“ 9月27日”的问题,就足够了:
事实证明,我们开始在许多帧中绘制150k更多的图元。通过将该数据与在两次测试运行之间的时间间隔合并的PR列表进行匹配(我们从图表中看到,它们之间相隔3天,但其中有2天是周末,没有进行测试),我们确定了“有罪”变更集及时。
但是,如果问题的根源是着色器变得更加复杂怎么办?还是更改抽奖顺序并因此增加透支额?还是深度缓冲区意外地开始保存到主存储器中,从而对带宽产生负面影响?
这些指标很难(在透支的情况下)或不可能(在着色器的复杂性和带宽的情况下)在游戏本身内进行追踪。这就是Arm Mobile Studio Pro发挥无价之宝并为我们提供帮助的地方。
Arm Mobile Studio Pro如何提供有关GPU负载的见解
Arm Mobile Studio Pro允许我们在CI服务器上执行自动测试的同时记录Mali系列GPU的硬件计数器,从而帮助我们解决了三种类型的任务:
1.找到以下问题的答案:“ GPU端到底发生了什么变化?” 在回归测试中
2.在新的内容测试过程中找到瓶颈,并了解需要优化的地方
3.在引入新的图形功能时,请有意识地选择目标设备(如我们一开始所提到的,我们支持种类繁多的设备,因此通常通过“图形设置”菜单激活图形功能)
对我们而言非常重要的是Arm Mobile Studio配备了一个名为Performance Advisor的工具,使我们能够将测试过程中记录的探查器跟踪显示为易于阅读的html报告。
让我们看看Arm Mobile Studio(尤其是Performance Advisor)如何加快解决类型3任务的速度。
最近,我们在引擎中添加了贴花,而我们的技术艺术家则面临着为竞技场几何图形和贴花重叠定义预算的任务。该任务的实质是:
- 定义我们要在其上提供此功能的目标设备
- 通过在现有FPS测试结果已经存在的地图上添加贴花来准备测试内容
- 对目标设备上内容已更改的构建运行自动测试
- 评估结果:如果FPS级别显着降低,请查看内容预算并返回到阶段2,或者查看目标设备列表
PA(性能顾问)大大简化了第4阶段。让我们假设在第一阶段,我们选择了带有Mali-G72 MP3的三星Galaxy A50作为目标设备。这是在此设备上运行的测试的PA报告的第一部分的外观(高图形质量设置,但暂时没有贴花):
主要观察结果:
- FPS在某些时候下降到30。好吧,如果没有PA,我们本可以了解到这一点。
- 在问题点,该设备显然是碎片绑定的。那个很有趣。我们可以使用贴花构建有关内容的预测。
我们使用贴花启动针对构建的测试,在工件中找到由PA生成的html报告,然后将其打开:
嗯...在此设备上,以及随着我们的技术美术师为第一次迭代添加的贴花数量,片段绑定帧的份额已显着增加。继续进行下一次迭代。
PA不会在任何情况下都直接向您显示瓶颈。例如,对于功能强大的设备,我们经常看到未知的局限性盛行:
在这种情况下,完整的捕获文件会有所帮助;您可以从测试运行的工件中下载这些文件,并使用Streamline对其进行分析。幸运的是,性能计数器在文档中进行了详细描述,并且Arm工程师随时准备提供咨询。
应当指出,Arm Mobile Studio专业版轻松,迅速地成为我们CI工作流程的一部分。除了方便的PA报告和探查器的完整跟踪信息外,我们还收到了一个JSON文件,其中包含PA报告中图表上显示的所有指标的平均值和百分位数。很快,我们计划将数据发送到bigquery并使用data studio对其进行可视化,就像我们对CPU事件探查器数据所做的一样。指标本身在此处进行了描述。
虽然Arm Mobile Studio仅允许我们为Mali系列GPU获取额外的数据,但它们是我们玩家群中使用最广泛的GPU。同样,我们可以从在Mali GPU系列设备上运行的测试中得出的许多观察结果对其他设备仍然有效(例如,如果Mali的带宽增加了,那么其他GPU的带宽可能也会增加,并且可能即使是其他平台)。
因此,对Arm表示敬意:您的工具可以解决我们在自动测试报告中缺少有关GPU性能的数据的问题。
结论
在MS-1(战争游戏),我们对例行工作自动化充满热情。性能测试已经自动化很长时间了,但是仍有改进的空间。
我们最近在测试报告的详细程度方面进行了巨大的努力,为我们提供了自动化框架,从而节省了测试和问题调查的时间。现在,我们可以跳过手动配置文件设置的枯燥阶段,从而发现我们的代码和内容存在很多问题。在自动化测试环境中收集概要分析数据不仅使它更易于访问,而且这种方法还可以提高该数据的质量:
- 稳定的测试环境意味着更稳定的数据(对于移动设备尤为重要,在室温下3-5°C的差异会影响测试结果)。
- 对历史数据的访问提供了一种将噪声与性能指标的重大变化区分开的方法。
数据质量极大地影响了分析速度。
我们认为,任何中型或大型游戏工作室都必须进行自动化性能测试。这不仅是为您的员工节省时间,还与测试和风险管理的质量有关:使用夜间测试,您无需担心最终测试中会弹出性能问题并影响发布时间表。