搜索 Unity

Unity 2021 LTS的性能分析:是什么?何时用?怎么用?

2022年6月1日 类别 Engine & platform | 23 分 阅读
A red mannequin in a 3d setting
A red mannequin in a 3d setting
分享

Is this article helpful for you?

Thank you for your feedback!

熟悉Unity的性能分析工具套件可能是你游戏开发秘籍里的最有用的技能之一。全面的性能分析可以极大地提高游戏的性能,所以我们发布一份新电子书:性能分析终极指南UNITY游戏(Ultimate guide to profiling Unity games)》,为你提供上手工具的重要诀窍。

每位游戏创作者都知道,流畅的性能对于游戏的代入感来说至关重要,而要做到身临其境,对游戏性能的分析必不可少。在分析时,你不仅得知道用哪些工具,还得知道怎样使用、何时使用这些工具。

这份70多页的高级性能分析指南是由Unity内外的专家们共同攥写的。它汇集了多种在Unity中分析应用性能、找出性能瓶颈的建议、知识以及最佳方法。 

现在我们来看看书中所包含的几条实用技巧吧。

何时分析

性能分析就像做侦探一样,你需要抽丝剥茧、揭开程序执行的神秘面纱,或者为什么某段代码会占用这么多内存。

性能分析工具能帮你了解项目的“黑盒子”里究竟在做什么。不要等到应用出现明显的性能问题时再去捣鼓这套工具箱。

你应当在项目开发前期就进行规划,以最大化性能分析的收益,而不是临发售才选择临时抱佛脚。性能分析应该是一个持续、主动、不断改进的过程。只要提早、经常性地分析性能,你和团队就可以深入理解并建立项目的“性能特征”。一旦性能骤降,你就能第一时间发现,并迅速纠正问题。

你也可以用一种简单的“三步走流程”在小范围内比较“分析前、分析后”的性能:第一步,在做出重大改动之前,分析并建立一条性能基准线。第二步,在修改期间进行分析,跟踪性能和性能预算,最后一步,在改动完成后进行分析,验证修改是否产生了预期的效果。

尽量用游戏的开发版进行分析,避免在Unity编辑器中分析。这是出于两个原因:

  1. 与编辑器中的应用相比,开发版的性能和内存使用更能反应真实情况。因为Profiler会记录编辑器本身的性能成本,导致结果出现偏差。
  2. 而且,部分性能问题只有在游戏运行于特定硬件或操作系统上时才会出现,假使你光在编辑器中分析性能,就会很容易错过这些问题。

可用工具

要想获得最准确的分析结果,你必须在实机上运行、分析项目,并使用平台的专用工具来发掘其硬件特性。

尽管Unity提供有一系列免费和强大的分析工具,让你能在编辑器内和实机上分析和优化代码,但有许多硬件平台也推出过自己的原生分析工具,如Arm、苹果、索尼和微软。组合这些工具能让你对所有目标硬件的性能有更全面的了解。

你可以在性能分析工具页了解所有现有可用的分析工具。

Unity的分析工具可在编辑器和Package Manager中找到。每种工具都能专门分析特定的运行流程(一种“环环相扣、部分构成整体”的工作流程)。你可以熟悉下以下分析器用于日常的使用:

  • Unity Profiler是你的切入点,也是你最常使用的工作面板。它会监测Unity编辑器和应用在播放模式下的性能,还能连接到在开发模式下运行应用的设备。Unity Profiler将收集并展示许多种性能数据,比如CPU时间的任务组成:从音频和物理到渲染和动画。请在这个性能分析的课程里上手工具。
  • Memory Profiler可以深入分析内存,找出项目和编辑器里可以优化的内存占用。Memory Profiler目前正处于预览阶段,预计将在Unity 2022 LTS中通过验证。
  • Profile Analyzer将汇总并可视化一组帧的画面和标记数据,帮助你推断数据在数帧上的活动,作为Unity Profiler单帧分析的补充。它还支持将两套数据集并排比较,明确某项改动会怎样影响应用的性能。
  • Frame Debugger支持暂停游戏回放到某一帧,再仔细查看该帧渲染时发起的绘图调用。除了能列出绘制调用外,Frame Debugger还支持查看每一步渲染,让你了解场景是怎样用图像元素一步步组建而成的。
  • Profiling Core软件包所包含的API可以提供某次分析记录的环境信息。

如何使用工具

Unity高级工程师Steve McGreal也是这本电子书的作者之一,他将工具的用法总结为以下简略图,欢迎随时参考。

关于工具的详细使用教程可以在电子书中找到,而这张流程图展示了工具使用流程的三个主要方面:

Flowchart for how to use the Profiler for pinpointing where to focus optimization efforts

你可以在此处下载流程图的PDF文件。更多内容请参见文末的分析工具使用教程资源链接。

帧是否能保持在预算内?

玩家们衡量性能的最常见方法就是观察帧率,或每秒帧数。不过,我们建议开发者们以毫秒为单位来计算帧时间。

比如,你的游戏在0.75秒内渲染了59帧,而第60帧则需要用0.25秒来渲染。60帧的平均帧率听起来不错,但在现实中,玩家都能注意到最后一帧的卡顿,因为它花了太长时间来渲染。

因此在分析和优化游戏时,我们需要尽量平均好每一帧的时间预算,只有这样才能营造出流畅和连贯的玩家体验。你需要根据自己的目标帧率来计算每一帧的时间预算。以一个30帧的应用为例,每一帧的渲染耗时应当时刻少于33.33毫秒(1000毫秒/30帧)。同样地,60帧应用的每帧耗时应小于16.66毫秒。

大多数现代主机和PC游戏的目标是达成60帧及以上的帧率。而在VR游戏中,我们则应该避免维持高帧率,以免导致玩家感到恶心或产生不适。移动端游戏也需要限制帧的时间预算,以避免设备过热。比如,某款手机游戏以30帧为目标,则每帧预算就只能在21-22毫秒,才能让CPU和GPU在两帧之间有喘息的机会。

请使用Unity Profiler来了解帧是否在预算之内。下方截图截取自某个被持续分析和优化的Unity移动游戏。该游戏在高配置手机上的目标是60帧,而在中配/低配手机上的目标是30帧,如截图中的手机。

Profiler framerate snapshot

这款游戏能在30帧/约22毫秒的帧预算内流畅运行,且不会产生过热现象。可以注意到主线程、VSync以及渲染线程和工作线程的灰色空闲时间段上都出现了许多WaitForTargetfps。此外,注意看Gfx在结束时的VBlank间隔。当前所有帧会在Timeline及上方的Time标尺中被画成一段时间标尺,来测量帧到帧的时间间隔。

如果你针对电池寿命和过热保护做出了一定的调整,并且每一帧仍能保持在预算之内,那么这一次性能分析就算是成功的,恭喜!接着再来看看内存占用是否也在预算之内。

然后,如果游戏超出了帧预算,下一步就是检测性能瓶颈。换句话说,就是找出CPU或GPU哪个占用了过长的时间。如果是CPU,就找到那条最忙的线程,这就是瓶颈所在。

性能分析的意义就在于找出限制瓶颈并针对性地优化。如果全靠猜,你优化的地方可能都不是关键的地方,而游戏的性能也几乎不会有改进。有些“优化”甚至会拖累游戏性能。

游戏是否受CPU主线程束缚?

主线程是所有游戏逻辑和脚本默认执行的地方;物理、动画、UI和渲染等游戏特色及系统都会在这里运行。

下方截图就展示了一个被主线程绑定的项目是什么样子的:

Capture from a project that is main thread-bound
一个主线程绑定的项目

尽管该应用的渲染线程和工作线程与前面的例子大差不离,都在帧预算之内,但这里的主线程在整张帧上都在忙于运行。即便算上Profiler在帧结束时产生的少量开销,主线程的忙碌时间也超过45毫秒,这意味着该项目的帧率会低于22帧。没有任何迹象表明主线程有空闲时间等待VSync完成;它在当前帧画面的整个过程中都非常忙碌。

于是,我们须在下一阶段中找出帧上最耗时的进程,以及其背后的根本原因。我们可以同时使用Unity Profiler和Profile Analyzer来检测并解决最耗性能的部分。制约性能的因素最常来自于物理、未经优化的脚本、Garbage Collector(GC)、动画、摄像机和UI。如果你仍不能明确问题的来源,可以试着用Deep Profiling、Call Stacks或者其他原生CPU分析器进行分析。

在我们总页数为95页的性能优化指南中,我们整理了一份常见陷阱的清单,方便你做好应对的准备。

游戏是否受CPU渲染线程束缚?

在渲染过程中,主线程会检查场景,并执行镜头剔除、深度排序和绘制调用批处理,将所有要渲染的东西列在一起。这个列表将被发给渲染线程,后者会将Unity内部的通用表达式转化为图形API来调动平台上的GPU工作。

在下方的Profiler记录中,你可以看到主线程在开始当前帧的渲染前会等待渲染线程,这由Gfx.WaitForPresentOnGfxThread 标记出来。

A render thread-bound scenario on Profiler
受渲染线程束缚的情形

渲染线程仍在提交前一帧的绘制调用命令,还未准备好接受来自主线程的新绘制调用。渲染线程在Camera.Render中花费了不少时间。

Rendering Profiler模块可以展示每一帧绘制调用批处理和SetPass调用的次数。而要调查哪次绘制调用批处理导致了渲染线程的问题,Frame Debugger就是最合适的工具。导致渲染线程性能受限的常见原因包括糟糕的绘制调用分批、同时存在多个活跃摄像机以及低效的镜头剔除。

应用是否受CPU工作线程束缚?

除了主线程或渲染线程外,应用受CPU工作线程束缚并不是那么常见,但如果项目使用了Data-Oriented Technology Stack (DOTS),则这种问题就有可能出现——特别是所有任务都用C# Job系统从主线程转移到工作线程时。

这是一段截取自编辑器运行模式的截图,这个DOTS项目正在CPU上运行粒子流体模拟:

A DOTS-based project, heavy on simulation, bound by worker threads
这个主要用于模拟的DOTS项目受到工作线程的束缚。

可以看到,工作线程上塞满了许多job。这表明有大量的任务被调离了主线程。请注意,主线程上48.14毫秒的帧时间和35.57毫秒的灰色WaitForJobGroupID标记表明,工作线程的工作负荷远超出单帧所能完成的符合。

WaitForJobGroupID的出现表明,主线程已经安排了任务在工作线程上异步运行,并且在等待工作线程上得出的结果。WaitForJobGroupID下方的蓝色Profiler标记显示了主线程在等待期间会运行job,试着让任务更快完成。

当然,你项目中的job不一定会像例子中那样并行运行。也许你将一段长任务放到了工作线程中运行。这的确可行,只要任务和完成时间的间隔足够长,它就可以运行。但如果间隔并不长,你就会看到主线程一直在等待job完成并停滞不前,如上面的截图。

你可以使用CPU Usage Profiler时间轴上的Flow Events功能来查看job任务被主线程安排运行及返回结果的时机。要想详细了解如何编写高效的DOTS代码,请参见我们的DOTS最佳实践

游戏是否受GPU束缚?

你可能会注意到主线程会等待渲染线程完成(如Profiler标记的Gfx.WaitForPresentOnGfxThread)。你的渲染线程中也可能会出现如Gfx.PresentFrame或.WaitForLastPresent等标记。这意味着应用是受GPU约束的。此时,你就需要将工作重点放在GPU上来提高整体性能。

下面的截图截取自运行Vulkan图形API的三星Galaxy S7。尽管例中Gfx.PresentFrame所耗费的部分时间可能与等待VSync有关,但这条非常长的Profiler标记表明了这里的大部分时间其实是在等待GPU完成上一帧的渲染。

A capture from a GPU-bound mobile game
一款受GPU约束的移动游戏

如果应用受GPU束缚,那么你就可以使用Frame Debugger来快速分析发送到GPU上的绘制调用批处理。不过,该工具并不提出具体的GPU时间信息,它只会揭开场景的组建方式。

要想仔细调查GPU上的性能限制,请根据你的目标硬件和图形API来选择合适的GPU分析器,再截取并检查GPU的运行。

导致GPU性能低下的常见原因包括低效的着色器、耗能过高的后处理效果、对透明图形的重复绘制(通常是粒子效果或UI)、体积巨大或未压缩的纹理、面数过多的模型网格,以及过高的输出分辨率(比如渲染4K画面)。

获取免费电子书

A promotion of a profiling e-book

性能优化和分析是一个庞大的主题。如果你想了解更多,请查看我们最近发布的电子书:Ultimate guide to profiling Unity games。书中包含超过80页的提示和技巧,所有内容由多位Unity专家合作攥写,其中也包括了我们的Integrated Support服务团队。

实际上,部分专家还协助编写了长达100页的移动PC/主机性能优化指南——其中包含了许多避免产生性能瓶颈的技巧。若想获取更多其他资源,请查看我们以前的物理、UI和音频设置移动端主机的图形与资产 ,以及内存和代码架构等主题的博文系列。

如果你希望让自己的团队直接获得Unity工程师的专家建议和项目指导,请在这里详细了解Unity的Success Plans

线上性能分析教学预告

3D model with robot figure on the right

我们新的Ultimate profiling tips网络教学将云集SYBO Games、Arm和Unity的专家,向大家介绍如何使用Unity及其他的原生分析工具来找出移动游戏常见的性能挑战。 

本次教学将涵盖:

  • 怎样编写精简的高性能代码和优化内存,让游戏在低端和高端设备上都能流畅运行
  • 如何避免过热保护、延长移动设备宝贵的电池寿命
  • 游戏各个开发阶段的性能分析策略,以及怎样在实测中建立坚固的方法论
  • 安卓性能分析的专家见解

欢迎加入我们将于6月14日11:00 am ET / 8:00 am PT(北京时间23:00)举办的圆桌会议和现场问答。

没看到想要的内容?

我们希望帮助用户充分利用起Unity应用。如果你有任何优化主题想要进一步探讨,请在论坛上告诉我们。我们也希望知道大家更喜欢哪种内容格式,这样我们就能够改进电子书和其他学习材料。

2022年6月1日 类别 Engine & platform | 23 分 阅读

Is this article helpful for you?

Thank you for your feedback!

加入论坛讨论