共计 5705 个字符,预计需要花费 15 分钟才能阅读完成。
性能提示
本节介绍了一些通用性能提示。许多人在考虑性能时白白浪费了时间。本指南旨在提供一个实用的方法,以便您只在关键地方研究性能。还有一些关于常见问题和陷阱的通用建议。
现代计算机速度很快
许多人低估了现代计算机的强大性能。现代硬件、操作系统、浏览器和 Construct 本身都非常快速且优化良好。许多项目即使从未投入任何努力来提高性能,最终也会有出色的性能。这是好事 – 这意味着您可以将宝贵的时间用于改进项目,而不是试图弄清楚如何提高性能。有时人们在问题出现之前就试图提高性能,这通常意味着您只是在浪费时间。这包括像“哪个更快,A 还是 B?”这样的问题 – 通常答案是“根本不重要,你在浪费时间”。
定期在目标设备上测试
如果您在高端游戏 PC 上预览项目,它很可能能够处理高强度的内容,而在较弱设备上可能会慢到无法忍受。这对于面向其他游戏玩家的 PC 游戏来说可能没问题,但对于面向典型消费者设备的内容来说可能太慢了。因此,定期在您预期典型玩家将使用的设备上测试项目仍然很重要,以确保在发布前能够发现任何问题。您越早发现性能问题,就越有可能知道是什么更改导致了它。最糟糕的情况是完成整个项目而不进行测试,然后发现它太慢,在这种情况下,您可能不知道为什么(尽管测量可以帮助,如下所述)。如前所述,您可能会发现整个开发过程中一切运行顺利,这是一个很好的结果,但最好是确定!
过去,移动设备的性能远低于桌面设备,通常需要特别考虑性能。然而,现在许多现代高端移动设备的性能已经与中端笔记本电脑相当,很可能也能很好地处理大多数类型的 Construct 内容。如果您想要针对特别低功耗的预算设备,可能需要特别小心。无论如何,如前所述,手头上有目标设备并定期测试,这样您可以确保!
测量,测量,再测量
获取关于性能问题的准确答案只有一个方法:测量。如果您不测量,或者猜测,或者在论坛上提问(让别人猜测),您可能会得到不准确的答案,最终浪费您的时间去优化对性能没有任何影响的东西。您必须使用测量并科学地证明什么会影响性能。
最最终的性能测量是每秒帧数(FPS)。如果 FPS 率良好,那么就没有必要优化任何东西!不要浪费时间。如果它不够好,项目运行缓慢,那么需要关注的关键测量是 CPU 和 GPU 利用率。您可以在 Construct 的 调试器 中找到所有这些测量值(仅限付费计划)
。
CPU 与 GPU
运行 Construct 项目有两个主要任务:运行逻辑,包括所有事件表、JavaScript 代码和行为 – 由 CPU(中央处理器)完成;绘制图形,包括视觉效果,由 GPU(图形处理器)完成。通常这些是两块不同的硬件(即使是在同一块芯片上也是不同的组件)。
如果 CPU 测量值很高,您可能需要优化项目逻辑。如果 GPU 测量值很高,您可能需要优化渲染。因此,这些测量将指导您的整体方法。
在这两种情况下,再一次强调,关键是 进行测量。要科学:尝试进行更改,并观察它如何影响关键性能测量。如果它没有产生影响,那么这个更改对性能无关紧要。如果您做出了正确的更改,您将看到可测量的差异。这也是回答“哪个更快,A 还是 B?”这类问题的方法:尝试两者并测量它们。(通常您会发现没有可测量的差异!)
以下各节提供了一些关于如何追踪您发现的有意义性能问题的原因和一些常见罪魁祸首的提示。
CPU 性能
CPU 通常负责除了绘制图形之外的所有事情。事件表、JavaScript 代码、插件、行为以及除图形之外的所有东西通常都在 CPU 上发生。
开始寻找 CPU 性能问题的最佳地点是 Construct 调试器中的CPU 分析器(仅限付费计划)
。这可以分解在不同领域花费的 CPU 时间,包括事件表中的单个事件组。如果您看到一个项目测量值特别高,这通常是要考虑优化的项目。例如,您可能会看到一个事件组本身使用了相当大比例的 CPU 时间。如果您查看该事件组,可能会发现它重复了一个事件数千次;调整它以减少工作可能会解决问题。
有时可能不太明显,例如处理行为所花费的时间。以下是一些可能导致高 CPU 使用率的一般性提示。和以前一样,检查这些的方法是依赖测量:尝试移除它们,或大幅减少它们的使用,并观察对测量值的影响。
- 物理行为:物理模拟非常消耗 CPU 资源。使用相对较少的带有物理行为的对象应该是可管理的。然而,如果您使用数千个带有物理行为的对象,它可能会导致显著的减速。
- 创建太多对象:虽然现代计算机和软件非常快速,但所有东西都有成本,即使是很小的成本。创建数千个对象可能会显著增加 CPU 使用率,具体取决于事件表、代码和行为运行的逻辑。
- 使用太多粒子:虽然单个粒子比对象更便宜,但它们仍然不是免费的。和创建太多对象一样,拥有太多粒子也可能导致高 CPU 使用率。
- 运行太多事件:如果您有一个非常大的项目,有数千个事件,这些事件都需要运行,这可能会导致显著的处理开销。通常大多数事件不需要一直检查。您可以通过将它们组织成事件组并禁用不需要的组来显著减少需要运行的事件数量。(禁用组中的事件会被跳过。)子事件也可以起到类似的作用,因为子事件只有在父事件为真时才会检查。
- 使用太多循环:使用太多如 For、For Each 和 Repeat 的循环可能会使项目变慢,尤其是如果它们被密集使用。嵌套循环尤其可能导致这种情况,因为它们迅速增加了迭代次数。要测试这是否是问题,可以尝试暂时禁用循环事件。
GPU 性能
GPU 通常只负责绘制图形 – 也就是说,将您的艺术品渲染到屏幕上,以及任何效果。
开始寻找 GPU 性能问题的最佳地点是 Construct 调试器中的GPU 分析器(仅限付费计划)
。这可以分解项目中的每个图层所花费的 GPU 时间。如果一个图层显示高测量值,那么很可能是该图层上的图形内容导致了高 GPU 使用率。例如,您可能会看到一个图层使用数百个带有效果的对象显示高测量值;移除效果或减少对象数量可能会解决问题。
填充率
关于 GPU 性能的一个重要观点是 填充率。在屏幕上绘制像素(也称为“填充”像素)需要将它们写入内存。绘制更多图像和更大图像需要写入更多像素到内存。将所有这些像素数据写入内存的数据率称为填充率。一旦填充率超过 GPU 内存带宽(数据可以写入的速率),项目就会开始减速,因为 GPU 无法跟上。请注意,这是硬件限制,而不是 Construct 或设备上的任何其他软件的限制。
要完全理解填充率,重要的是还要知道 Construct 是 从后向 前渲染项目的。这意味着它从绘制背景(Z 顺序最低的对象)开始,然后逐步在顶部绘制所有其他内容,直到达到最前端。由于顶部的对象最后绘制,它们出现在顶部。然而,当对象重叠时,这将涉及重复写入相同的像素,这会浪费填充率,即下面的对象仍然消耗内存带宽,即使它后来被上面的东西覆盖。因此,填充率的最坏情况是一堆大型重叠图像。
关于填充率还有几点需要注意:
- 1. 图像的透明区域仍然会消耗填充率。换句话说,透明像素仍然会被渲染,它们只是没有视觉效果。
- 2. 使用自身纹理的图层(在属性栏中标记为使用自身纹理)在图层渲染完成后必须复制到屏幕上。这意味着每个使用自身纹理的图层都相当于渲染了一个覆盖所有内容的屏幕大小精灵。拥有太多使用自身纹理的图层会迅速消耗您的可用填充率。
简而言之,屏幕上绘制的像素越多,GPU 的工作量就越大。这包括透明像素、重叠图像和使用自身纹理的图层。
GPU 性能提示
以下是一些可能导致渲染性能缓慢的一般性提示。和以前一样,检查这些的方法是依赖测量:尝试移除它们,或大幅减少它们的使用,并观察对测量值的影响。
- 避免使用带有大片透明区域的对象。裁剪您使用的所有图像以去除无用的透明空间。(这也节省内存!)将带有大片透明区域的大型对象分解成一系列较小的对象。例如,添加一个使用屏幕大小透明精灵的窗口边界,由于其中间有一个大块透明区域,因此性能会很差。将其分解为四个独立的边缘对象要高效得多,因为渲染区域更小。
- 避免对象之间有太多重叠区域。重叠区域将反复渲染像素,这会浪费填充率。
- 避免使用太多使用自身纹理的图层。启用强制使用自身纹理、更改不透明度或混合模式,或添加效果,都会导致图层渲染到自己的纹理,这会消耗大量填充率。虽然这在某些情况下是必要的,以获得所需的视觉效果,但应避免在同一布局中的图层多次这样做。
- 避免使用太多效果。虽然效果在视觉上令人印象深刻,但将大量效果添加到图层或对象上会显著增加 GPU 的渲染工作量。某些类型的效果比其他类型的效果性能开销更大。如果您有大量对象都有相同的效果,可以尝试将这些对象放在一个带有图层效果的图层上,或者在每个对象上单独应用效果;有时一种方法可能比另一种更高效。
- 避免不必要的使用效果。永远不要使用效果来处理对象上的静态效果。例如,不要使用灰度效果使对象始终显示为灰度。当您可以简单地导入一个灰度图像而不使用任何效果时,这会降低性能。
- 没有硬件加速。在某些情况下,GPU 可能根本不会被使用,此时 CPU 将被迫执行所有渲染工作,这通常要慢得多。这通常是由系统级问题引起的,例如硬件或软件过时,或图形驱动程序损坏。它也可能受浏览器设置的影响(例如,关闭“使用硬件加速”)。您可以通过访问 chrome://gpu
- 在地址栏中检查 Chrome 的硬件加速状态。您应该看到 WebGL 列为硬件加速(绿色)。Construct 支持 WebGL 和 WebGL 2;只要其中之一是硬件加速的,Construct 就会选择它。
解释性能测量
关于 Construct 性能测量需要注意的是,CPU 和 GPU 测量是基于计时器的。这使得它们容易受到硬件电源管理的影响,CPU 和 GPU 都会使用电源管理。
要理解电源管理如何影响计时器测量,可以考虑一个现代处理器,它可以以半速运行在低功耗模式下。在满功率模式下,一个任务可能需要 5 毫秒来完成。然而,如果不在显著负载下,它会切换到低功耗模式,不仅是为了节省电力(对于电池供电设备尤其重要),也是为了避免芯片过热。在这种模式下,任务将需要 10 毫秒来完成。由于 Construct 的测量是基于计时器的,这意味着它看起来像是占用了两倍的处理器时间。然而,这并不是处理器满容量的真实反映。
现代处理器的电源管理方案比这要复杂得多,通常涉及多种电源模式,它们在性能和功耗之间有不同的权衡,并且会根据系统负载和温度测量不断在这些模式之间切换。然而,关键点是计时器基础的测量可能会因电源管理以不可预测的方式变化。这可能导致一些异常的测量,尤其是在低功耗模式下(当系统大部分处于空闲状态)– 您可能会看到使用率测量突然下降,因为工作量增加时处理器 stepping up 进入更高的功率模式。CPU 和 GPU 使用率测量对于解决性能问题有帮助,但请记住它们并不完全准确。特别是它们对于“微基准测试”并不可靠,例如测试两个小测试哪个更快,因为测量主要反映硬件电源模式。这也是为什么您不应该在发现真正问题之前尝试优化性能的原因!
还值得注意 Construct 的测量仅针对您的项目,CPU 测量仅针对主线程(即单个核心)。它们不是系统范围的测量,并且可能会受到系统其他活动的影响。CPU 测量不包括在后台线程上完成的工作,这在某些情况下也可能是重要的,但通常不会直接贡献到帧率。
记住,帧率(FPS)是最终的性能衡量标准:只要帧率良好,那么整体性能就没问题。其他的测量指标是为了在帧率下降时帮助您诊断可能存在的问题。
运行时的性能显示
虽然 Construct 的调试器会显示关键的性能测量值,但有时在项目本身中显示这些值会很有用,例如 仅用于 ** 远程预览 ** 付费计划的测试
或在导出的项目中。
以下三个系统表达式提供了基本的性能测量值。
- fps – 返回当前每秒的帧数。最大帧率取决于显示器的刷新率,通常为 60。
- CPUutilisation – 返回当前估计的 CPU 使用率,范围从 0 到 1。表达式
round(cpuutilisation * 100)
将返回一个百分比。请注意,这受到“性能测量解释”下的注意事项的限制。 - GPUutilisation – 返回当前估计的 GPU 使用率,范围从 0 到 1。表达式
round(gpuutilisation * 100)
将返回一个百分比。请注意,此测量值在某些设备上可能不可用(在这种情况下,它将显示为 NaN,代表非数字)。这也受到“性能测量解释”下的注意事项的限制。
您可以使用文本对象在项目中显示这些值,以便在测试项目时关注性能,使用每帧更新的动作:
将文本设置为 fps & " FPS, " & round(cpuutilisation * 100) & "% CPU, " & round(gpuutilisation * 100) & "% GPU"
这将显示类似于 “60 FPS,30% CPU,40% GPU”
的字符串,指示帧率和大致的 CPU 及 GPU 使用率。
常见的误解
以下这些事情经常被指责会影响性能,但通常影响很小或没有影响。
- 离屏对象 不会 被渲染。Construct 不会为未出现在窗口中的对象发出绘制调用,并且 GPU 也足够智能,知道不渲染出现在窗口外的任何内容 – 即使单个图像仅部分在屏幕上。
- 图像格式(例如 JPEG、PNG 或 WebP)会影响下载大小,但对运行时性能或内存使用没有影响。所有图像在启动时都会被解压缩为 32 位位图。
- 音频格式也只会影响下载大小,但对运行时性能没有影响。
- 图层数量通常没有影响。使用自己纹理的图层会有性能开销,如上所述。然而,具有默认设置的图层本身不使用自己的纹理,并且本身没有性能开销。您可以随意使用任意数量的这些图层。
- 布局数量也不太可能对性能产生影响。布局大小也没有直接影响;较大的布局不会使用更多内存或需要更多处理,除非您使用更多对象。
- 对象的角度或不透明度以及浮点数位置(例如将精灵定位在 X = 10.5)通常没有影响,因为现代图形芯片非常擅长处理这些,即使在性能较弱的设备上也是如此。使用大量非常大的精灵有时仍可能导致减速 – 请参阅关于填充率的部分。
总结
简而言之,在考虑性能时,以下是关键要点:
- 定期在目标设备上进行测试。
- 如果项目足够快,就不要尝试优化。您只会浪费时间。
- 如果不够快,依靠测量值来指导您的优化。
- 每秒帧数(FPS)是最终的测量标准。CPU 和 GPU 使用率是基于时间的近似值,主要用于帮助您进行性能测量以指导优化。