利用 Android 动态性能框架优化散热和 CPU 性能

本指南介绍了如何使用 Android 动态性能框架 (ADPF) 根据 Android 上的动态散热、CPU 和 GPU 管理功能优化游戏。这些功能侧重于游戏,但也可以用于其他性能密集型应用。

ADPF 是一组 API,可让游戏和性能密集型应用更为直接地与 Android 设备的电源和散热系统进行互动。借助这些 API,您可以监控 Android 系统上的动态行为,在不造成设备过热问题的可持续界限内优化游戏性能。

与桌面设备和游戏机相比,移动 SoC 和 Android 具有更多的动态性能行为。这些行为包括热状态管理、不同的 CPU 和 GPU 时钟以及不同的 CPU 核心类型。加之 SoC 的核心拓扑结构日益多样化,使得试图确保您的游戏能够利用这种行为而不对设备性能产生负面影响变得困难重重。ADPF 提供了其中的一些信息,以提高性能的可预测性。

以下是主要的 ADPF 功能:

  • 热状态监控:监控设备的热状态,然后在设备性能变得不可持续之前主动调整性能。

  • CPU 性能提示:提供性能提示,让 Android 选择适当的 CPU 时钟和核心类型,而不是让 Android 根据之前的工作负载进行选择。

  • 固定性能模式:在进行基准化分析时在设备上启用固定性能模式,以获取不会因动态 CPU 时钟设置而更改的测量结果。

热状态监控

已发布:Android 11(API 级别 30)
所有设备必备:Android 13(API 级别 33)或更高版本

应用的潜在性能受设备热状态的限制,热状态可能会因天气、近期使用情况以及设备热设计等特性而异。设备只能在限定的时间内保持高水平的性能,然后便会受到热限制。实现的关键目标是在不超出热限制的情况下实现性能目标。此外,在调试性能问题时,了解设备热状态对性能造成限制的时机非常重要。

游戏引擎通常具有运行时性能参数,可以调整引擎对设备施加的工作负载。例如,这些参数可以设置工作器线程数量、大核心和小核心的工作器线程亲和性、GPU 保真度选项以及帧缓冲区分辨率。

当设备接近不安全的热状态时,您的游戏可以通过借助这些参数降低工作负载来避免受到限制。为避免受到限制,您应监控设备的热状态并主动调整游戏引擎工作负载。设备过热后,工作负载必须降至可持续的性能水平以下,以便进行散热。

PowerManager

ADPF 提供 PowerManager 类,用于监控设备热状态。以下是其主要元素:

您可以通过轮询 getThermalHeadroom 方法来监控设备的热状态。此方法用于确定设备可以在不过热的情况下保持当前性能水平多长时间。如果时间低于运行工作负载所需的时间量,您的游戏应将工作负载降低到可持续水平。例如,游戏可以切换到较小的核心、降低帧速率或降低保真度。

CPU 性能提示

已发布:Android 12(API 级别 31)
所有设备必备:尚未要求

借助 CPU 性能提示,游戏可以影响动态 CPU 性能行为,而不会使设备过热以及浪费电量。在大多数设备上,Android 会根据先前的需求为工作负载动态调整 CPU 时钟速度和核心类型。如果工作负载使用的 CPU 资源较多,则时钟速度会提高,且工作负载最终会移至更大的核心。如果工作负载使用的资源较少,Android 会调低资源分配量。

时钟速度

当 Android 设备动态调整 CPU 时钟速度时,频率可能会改变代码对性能的影响。设计可处理动态时钟速度的代码对于最大限度地提高性能、保持安全的热状态以及高效使用电量非常重要。您可以通过以峰值时钟速度运行游戏来暂时减少卡顿并提高响应速度,但这会消耗电量,最终导致时钟受到热限制。当 CPU 或 GPU 时钟受到热限制时,它们的运行性能会低于可持续界限。

您无法在应用代码中直接分配 CPU 频率。因此,应用尝试以较高的 CPU 时钟速度运行的一种常用方法是在后台线程中运行忙循环,使工作负载看起来需要更多资源。当应用未使用其他资源时,这会浪费电量并增加设备上的热负载。

核心类型

运行游戏的 CPU 核心类型是影响性能的另一项重要因素。Android 设备通常会根据近期的工作负载行为动态更改分配给线程的 CPU 核心。在具有多个核心类型的 SoC 上,CPU 核心分配会更加复杂。在某些此类设备上,较大的核心仅供短暂使用,而不会陷入热不可持续状态。

您的游戏不应出于以下原因尝试设置 CPU 核心亲和性:

  • 工作负载的最佳核心类型因设备型号而异。

  • 运行较大核心的可持续性因 SoC 和每个设备型号提供的不同散热解决方案而异。

  • 对热状态的环境影响可能使核心选择变得更加复杂。例如,天气或手机壳可能会改变设备的热状态。

  • 核心选择无法适应具有额外的性能和散热功能的新设备。因此,设备通常会忽略游戏的处理器亲和性。

PeformanceHintManager

ADPF 提供了 PerformanceHintManager 类,以便游戏可以针对 CPU 时钟速度和核心类型向 Android 发出性能提示。然后,操作系统可以根据设备的 SoC 和散热解决方案决定如何充分利用这些提示。如果您的应用将此 API 与热状态监控功能结合使用,则可以为操作系统提供更明智的提示,而无需使用忙循环和其他可能导致受限制的编码方法。

游戏使用性能提示的方式如下:

  1. 针对行为类似的键线程创建提示会话。例如:

    • 渲染线程获得一个会话
    • IO 线程获得另一会话
    • 音频会话获得第三个会话

    游戏应尽早执行此操作,至少要比会话需要更多系统资源的时间提前 2 毫秒(最好超过 4 毫秒)。

  2. 在每个提示会话中,预测每个会话运行所需的时长。典型时长相当于帧间隔,但如果各帧的工作负载没有显著变化,应用使用的间隔可能会更短。

固定性能模式

已发布:Android 11(API 级别 30)
所有设备必备:尚未要求

Android 设备可以根据系统负载动态更改时钟设置。此行为对于在使用期间节省电量非常有帮助,但可能会导致难以获取可靠的性能数据。如果您尝试确定代码 fragment 的运行速度有多快以防止出现回归问题,或者如果优化可重复,那么如果未以固定的时钟速度进行测试,结果就会不可靠。借助固定的时钟,您可以准确地对性能进行 A/B 测试,而无需将 CPU 频率更改作为一项因素。

固定性能模式会设置 CPU 和 GPU 时钟的上限和下限。此模式不会停用其他动态性能行为,例如核心选择。

您可以使用以下 adb 命令启用固定性能模式:

adb shell cmd power set-fixed-performance-mode-enabled [true|false]

以固定性能模式运行的设备可能仍会过热,因为该模式并不会使设备进入热可持续状态。因此,我们建议在运行基准测试时执行以下操作:

  • 等待设备恢复到热可持续状态,然后再开始运行。

  • 在测试期间监控设备的热状态,以区分基准测试代码和热事件的影响。

示例应用

ADPF 示例应用演示了 ADPF API 的基本用法。该示例使用 ADPF getThermalHeadroom API 和热状态 API 展示了设备的热状态。该应用还会根据 API 的提示和 PerformanceHintManager API 动态更改工作负载,以控制渲染线程性能。