使用 Simpleperf 评估设备的性能。Simpleperf 是一款适用于 Android 上应用和原生进程的原生分析工具。使用 CPU 分析器 实时检查应用 CPU 使用率和线程活动。
性能有两个用户可见的指标
- 可预测、可感知的性能。用户界面 (UI) 是否丢帧或始终以 60FPS 渲染?音频播放是否没有伪影或爆音?用户触摸屏幕到效果显示在显示屏上的延迟有多长?
- 较长操作所需的时间长度(例如打开应用)。
第一个比第二个更引人注目。用户通常会注意到卡顿,但除非他们并排查看两台设备,否则他们无法分辨 500 毫秒与 600 毫秒的应用启动时间。触摸延迟会立即被注意到,并显着影响设备感知。
因此,在快速设备中,UI 管道是系统中最重要的东西,除了保持 UI 管道正常运行所必需的东西。这意味着,如果可以运行 UI 工作,则 UI 管道应优先于任何其他不必要的非 UI 工作。为了保持流畅的 UI,如果可以运行 UI 工作,则必须延迟后台同步、通知传递和类似工作。为了保持流畅的 UI,可以牺牲较长操作(HDR+ 运行时、应用启动等)的性能。
容量与抖动
在考虑设备性能时,容量和抖动是两个有意义的指标。
容量
容量是设备在一段时间内拥有的某种资源的总量。这可以是 CPU 资源、GPU 资源、I/O 资源、网络资源、内存带宽或任何类似的指标。在检查整个系统性能时,抽象各个组件并假设确定性能的单个指标可能很有用(尤其是在调整新设备时,因为在该设备上运行的工作负载可能是固定的)。
系统的容量因在线计算资源而异。更改 CPU/GPU 频率是更改容量的主要手段,但还有其他手段,例如更改在线 CPU 核心的数量。因此,系统的容量与功耗相对应;更改容量总是会导致功耗发生类似的变化。
给定时间所需的容量主要由正在运行的应用决定。因此,平台在调整给定工作负载所需的容量方面几乎无能为力,而调整方法仅限于运行时改进(Android 框架、ART、Bionic、GPU 编译器/驱动程序、内核)。
抖动
虽然工作负载所需的容量很容易看到,但抖动是一个更模糊的概念。为了更好地了解抖动作为快速系统障碍的介绍,我们建议阅读题为缺失的超级计算机性能案例:在 ASCI Q 的 8,192 个处理器上实现最佳性能的论文。(这是一项关于 ASCI Q 超级计算机为何未达到预期性能的调查,并且是优化大型系统的绝佳入门介绍。)
本页面使用术语“抖动 (jitter)”来描述 ASCI Q 论文中所说的噪声。抖动是阻止可感知工作运行的随机系统行为。它通常是必须运行的工作,但可能没有严格的定时要求使其在特定时间运行。由于它是随机的,因此极其难以反驳给定工作负载存在抖动。同样极其难以证明已知的抖动源是特定性能问题的原因。最常用于诊断抖动原因的工具(例如跟踪或日志记录)可能会引入它们自身的抖动。
在 Android 的实际实现中遇到的抖动来源包括:
- 调度器延迟
- 中断处理程序
- 驱动程序代码在禁用抢占或中断的情况下运行时间过长
- 长时间运行的软中断 (softirqs)
- 锁竞争(应用、框架、内核驱动程序、Binder 锁、mmap 锁)
- 文件描述符竞争,其中低优先级线程持有文件的锁,阻止高优先级线程运行
- 在工作队列 (workqueues) 中运行 UI 关键代码,这可能会导致延迟
- CPU 空闲状态转换
- 日志记录
- I/O 延迟
- 不必要的进程创建(例如,
CONNECTIVITY_CHANGE
广播) - 由可用内存不足引起的页面缓存抖动 (thrashing)
给定抖动周期所需的时间量可能会或可能不会随着容量的增加而减少。例如,如果驱动程序在等待通过 i2c 总线读取数据时禁用中断,则无论 CPU 频率为 384 MHz 还是 2 GHz,都将花费固定的时间量。当涉及到抖动时,增加容量并不是改善性能的可行解决方案。因此,更快的处理器通常不会改善抖动受限情况下的性能。
最后,与容量不同,抖动几乎完全属于系统供应商的领域。
内存消耗
内存消耗传统上被认为是性能不佳的原因。虽然消耗本身不是性能问题,但它可能通过 lowmemorykiller 开销、服务重启和页面缓存抖动引起抖动。减少内存消耗可以避免性能不佳的直接原因,但也可能有其他有针对性的改进措施可以避免这些原因(例如,锁定框架以防止其在稍后很快被换入时被换出)。
分析初始设备性能
从功能正常但性能不佳的系统开始,并试图通过查看用户可见的个别性能不佳案例来修复系统的行为,不是一个明智的策略。由于性能不佳通常不容易重现(即抖动)或属于应用问题,因此完整系统中的变量太多,使得此策略无效。因此,很容易错误地识别原因并进行细微的改进,同时错失在整个系统中修复性能的系统性机会。
相反,在启动新设备时,请使用以下通用方法:
- 使系统启动到 UI,并运行所有驱动程序和一些基本频率调节器设置(如果您更改频率调节器设置,请重复以下所有步骤)。
- 确保内核支持
sched_blocked_reason
跟踪点以及显示管道中的其他跟踪点,这些跟踪点指示帧何时传递到显示屏。 - 在运行轻量级且一致的工作负载(例如,UiBench 或 TouchLatency 中的球体测试)时,对整个 UI 管道(从通过 IRQ 接收输入到最终扫描输出)进行长时间跟踪。
- 修复在轻量级且一致的工作负载中检测到的丢帧。
- 重复步骤 3-4,直到您可以连续运行 20 秒以上且不丢帧。
- 继续处理其他用户可见的卡顿 (jank) 来源。
在设备启动初期,您可以执行的其他简单操作包括:
- 确保您的内核具有 sched_blocked_reason 跟踪点补丁。此跟踪点通过 systrace 中的 sched 跟踪类别启用,并在线程进入不可中断睡眠时提供负责睡眠的函数。它对于性能分析至关重要,因为不可中断睡眠是抖动的一个非常常见的指标。
- 确保您有足够的 GPU 和显示管道的跟踪。在最近的 Qualcomm SOC 上,跟踪点使用以下方式启用:
adb shell "echo 1 > /d/tracing/events/kgsl/enable"
adb shell "echo 1 > /d/tracing/events/mdss/enable"
当您运行 systrace 时,这些事件保持启用状态,因此您可以在 mdss_fb0
部分的跟踪中看到有关显示管道 (MDSS) 的其他信息。在 Qualcomm SOC 上,您不会在标准 systrace 视图中看到有关 GPU 的任何其他信息,但结果会出现在跟踪本身中(有关详细信息,请参阅 了解 systrace)。
您希望从这种显示跟踪中获得的是一个直接指示帧已传递到显示屏的单一事件。从那里,您可以确定您是否成功达到了帧时间;如果事件 Xn 在事件 Xn-1 之后不到 16.7 毫秒发生(假设为 60 Hz 显示屏),那么您就知道您没有卡顿。如果您的 SOC 不提供此类信号,请与您的供应商合作以获取它们。如果没有帧完成的明确信号,调试抖动将极其困难。
使用合成基准测试
合成基准测试对于确保设备的基本功能存在很有用。但是,将基准测试作为感知设备性能的代理是无用的。
根据 SOC 的经验,SOC 之间合成基准测试性能的差异与可感知的 UI 性能(丢帧数、第 99 百分位帧时间等)的类似差异无关。合成基准测试是仅限容量的基准测试;抖动仅通过从基准测试的批量操作中窃取时间来影响这些基准测试的测量性能。因此,合成基准测试分数作为用户感知性能的指标大多是无关紧要的。
考虑两个 SOC 运行基准测试 X,该基准测试渲染 1000 帧 UI 并报告总渲染时间(分数越低越好)。
- SOC 1 在 10 毫秒内渲染基准测试 X 的每一帧,得分为 10,000。
- SOC 2 在 1 毫秒内渲染 99% 的帧,但在 100 毫秒内渲染 1% 的帧,得分为 19,900,这是一个明显更好的分数。
如果基准测试指示实际的 UI 性能,则 SOC 2 将无法使用。假设刷新率为 60 Hz,SOC 2 将每 1.5 秒的操作出现一次卡顿帧。同时,SOC 1(根据基准测试 X,速度较慢的 SOC)将非常流畅。
使用错误报告
错误报告有时对性能分析很有用,但由于它们非常繁重,因此很少用于调试零星的卡顿问题。它们可能会提供一些关于系统在给定时间正在做什么的提示,特别是如果卡顿发生在应用转换附近(这会在错误报告中记录)。错误报告还可以指示系统何时出现更广泛的错误,这可能会降低其有效容量(例如,热节流或内存碎片)。
使用 TouchLatency
一些不良行为的示例来自 TouchLatency,它是 Pixel 和 Pixel XL 使用的首选周期性工作负载。它位于 frameworks/base/tests/TouchLatency
,并且有两种模式:触摸延迟和弹跳球(要切换模式,请单击右上角的按钮)。
弹跳球测试正如其外观一样简单:一个球在屏幕上永远弹跳,无论用户输入如何。它通常也是迄今为止最难完美运行的测试,但是它越接近无丢帧运行,您的设备就会越好。弹跳球测试之所以困难,是因为它是一个微不足道但完全一致的工作负载,以非常低的频率运行(这假设设备具有频率调节器;如果设备改为以固定频率运行,则在首次运行弹跳球测试时将 CPU/GPU 降频至接近最小值)。随着系统静止并且频率降至更接近空闲状态,每帧所需的 CPU/GPU 时间会增加。您可以观看球并看到卡顿,并且您还可以在 systrace 中看到丢帧。
由于工作负载非常一致,因此通过跟踪在每个丢帧期间(而不是 UI 管道)系统上到底在运行什么,您可以比在大多数用户可见的工作负载中更容易地识别大多数抖动源。较低的频率会放大抖动的效果,使其更有可能任何抖动都会导致丢帧。因此,TouchLatency 越接近 60FPS,您就越不可能遇到导致较大应用中出现零星、难以重现的卡顿的不良系统行为。
由于抖动通常(但并非总是)与时钟速度无关,因此出于以下原因,请使用以非常低的时钟频率运行的测试来诊断抖动:
- 并非所有抖动都与时钟速度无关;许多来源只是消耗 CPU 时间。
- 调节器应通过降低时钟频率使平均帧时间接近截止时间,因此运行非 UI 工作所花费的时间可能会将其推到丢帧的边缘。