评估性能

您可以使用 Simpleperf 来评估设备的性能。Simpleperf 是一款适用于 Android 平台上的应用和本机进程的原生分析工具。您可以使用 CPU Profiler 来实时检查应用的 CPU 使用率和线程活动。

在性能方面,有两项用户可见指标:

  • 可预测、可察觉的性能。界面会丢帧还是始终以 60 帧/秒的帧速率渲染?音频在没有工件或弹出的情况下会播放吗?用户在触摸屏幕后要多久显示屏上才会显示相应结果?
  • 耗时操作所需的时间长短(如打开应用)。

前者比后者更显而易见。用户通常会注意到卡顿情况,但分辨不出 500 毫秒和 600 毫秒应用启动时间的差别,除非将两台设备并排进行对比。触摸延迟立刻就能被发现,且严重影响用户对设备的印象。

因此,在速度较快的设备中,除了使界面通道保持正常运转所必需的要素,界面通道是系统中最重要的部分。这意味着,如果不是保持界面流畅运转所必需的任务,都应为界面通道让路。要让界面保持流畅运转,后台同步、通知发送及类似的任务都必须延迟(如果界面任务可以运行的话)。可以牺牲耗时操作(HDR+ 运行时、应用启动等)的性能来保持界面的流畅性。

容量和抖动

在考虑设备性能时,容量和抖动是两项重要指标。

容量

容量是设备在一段时间内拥有的某种资源的总量。这种资源可以是 CPU 资源、GPU 资源、I/O 资源、网络资源、内存带宽或任何类似指标。在检查整个系统的性能时,抽取各个组件并假设单项指标决定着性能会很有用(尤其是调优新设备时,因为在新设备上运行的工作负载可能是固定的)。

系统的容量因在线计算资源而异。 更改 CPU/GPU 频率是改变容量的主要方式,但也有其他方式,如更改在线 CPU 核心数。相应地,系统的容量与耗电量相对应,改变容量一定会导致耗电量出现类似的变化

在给定时间所需的容量在绝大多数情况下取决于正在运行的应用。因此,平台几乎不能调整给定工作负载所需的容量,调整所用的方式也仅限于运行时改进(Android 框架、ART、Bionic、GPU 编译器/驱动程序、内核)。

抖动

工作负载所需的容量很容易看出来,抖动却是一个比较模糊的概念。有关抖动是快速系统的一种障碍的详细介绍,请参阅 THE CASE OF THE MISSING SUPERCOMPUTER PERFORMANCE: ACHIEVING OPTIMAL PERFORMANCE ON THE 8,192 PROCESSORS OF ASCl Q。(这是一项针对 ASCI Q 超级计算机为何达不到预期性能的调查,同时详细介绍了如何优化大型系统。)

本页使用“抖动”一词来描述 ASCI Q 论文中提到的噪点。抖动是一种随机的系统行为,会阻止可察觉任务的运行。通常是必须运行的任务,但可能没有严格的定时要求,不要求在任何特定时间运行。因为抖动具有随机性,所以很难反驳给定的工作负载存在抖动,也很难证明已知的抖动源是导致特定性能问题的原因。诊断抖动原因最常用的工具(如跟踪或日志记录)可能会引入它们自己的抖动。

在实际的 Android 实现中遇到的抖动源包括:

  • 调度程序延迟
  • 中断处理程序
  • 驱动程序代码在抢占或中断被停用的情况下运行时间过长
  • 运行时间较长的软中断
  • 锁争用(应用、框架、内核驱动程序、binder 锁、mmap 锁)
  • 文件描述符争用,低优先级的线程持有某个文件的锁,以阻止高优先级的线程运行
  • 在工作队列中运行可能会延迟的界面关键型代码
  • CPU 空闲转换
  • 记录
  • I/O 延迟
  • 创建不必要的进程(如 CONNECTIVITY_CHANGE 广播)
  • 可用内存不足所导致的页面缓存抖动

给定时间段内的抖动所需的时间不一定会随着容量的增加而减少。例如,如果驱动程序在等待从 i2c 总线上读取数据时使中断处于停用状态,那么无论 CPU 是 384MHz 还是 2GHz,所需的时间都是固定的。涉及抖动时,增加容量并非提升性能的可行解决方案。因此,在受抖动限制的情况下,速度更快的处理器通常不会提升性能

最后,与容量不同的是,抖动几乎完全存在于系统供应商的网域中。

内存消耗

一直以来,人们都将性能不佳归因于内存消耗。虽然消耗本身不是性能问题,但是它可能会通过 lowmemorykiller 开销、服务重启和页面缓存抖动引起抖动。减少内存消耗可以避免导致性能不佳的直接原因,但可能还有其他具有针对性的改进可避免这些原因(例如,固定框架以防止它在不久之后将被换入时却被换出)。

分析初始设备性能

从运行正常但性能不佳的系统入手,并尝试通过研究用户可见性能不佳的个别情况来修复系统的行为,这种做法并非良策。因为性能不佳通常不易重现(如抖动)或者由应用问题导致,所以整个系统中阻止此策略发挥作用的可变因素非常多。因此,很容易错误地识别原因并做出微小的改进,而错失修复整个系统性能的系统性机会。

相反,在启动新设备时,请使用以下常规方法:

  1. 使系统启动到包含所有正在运行的驱动程序以及一些基本的频率调节器设置的界面(如果更改频率调节器设置,请重复以下所有步骤)。
  2. 确保内核支持 sched_blocked_reason 跟踪点以及显示通道中指示何时将帧发送到显示屏的其他跟踪点。
  3. 在运行轻量级的一致性工作负载(例如,UiBenchTouchLatency 中的球测试)的同时,对整个界面通道(从通过 IRQ 接收输入到最终的扫描输出)进行长时间的跟踪。
  4. 修复在轻量级的一致性工作负载中检测到的丢帧问题。
  5. 重复执行第 3-4 步,直到您可以在零丢帧的情况下一次运行 20 秒以上的时间。
  6. 转向用户可见的其他卡顿源。

您可以在设备启动早期执行的其他简单操作包括:

  • 确保您的内核有 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 毫秒内(假设使用 60Hz 的显示屏),您就会知道没有卡顿。如果您的 SOC 不提供此类信号,请与您的供应商联系以获取。如果没有明确的帧完成信号,很难调试抖动。

使用合成基准

合成基准有助于确保设备的基本功能是存在的。不过,将基准视为感知设备性能的代理毫无用处。

根据使用 SOC 所得到的经验,SOC 之间的合成基准性能的差异与可察觉的界面性能(丢帧数、第 99 个百分位帧时间等)中的类似差异不相关。合成基准属于仅限容量的基准;抖动仅可以从基准的批量操作中窃取时间来影响这些基准衡量的性能。因此,在作为用户感知性能的指标时,合成基准得分基本上不相关。

假设有两个 SOC 正在运行基准 X,它可渲染 1000 帧的界面,并报告总渲染时间(得分越低越好)。

  • SOC 1 渲染基准 X 的每一帧需要 10 毫秒,得分为 10000。
  • SOC 2 渲染 99% 的帧需要 1 毫秒,但渲染 1% 的帧需要 100 毫秒,得分为 19900,得分明显更高。

如果基准反映了实际的界面性能,则 SOC 2 将根本不能用。假设刷新率为 60Hz,那么每执行 1.5 秒的操作,SOC 2 就会出现一次卡顿帧。相比之下,SOC 1(根据基准 X 得出的较慢的 SOC)将会非常流畅。

使用错误报告

错误报告有时对于性能分析非常有用,但是因为这类报告的内容全面而复杂,因此对调试时有时无的卡顿问题用处不大。错误报告可能会提供一些线索,让您了解系统在给定的时间正在执行什么操作,尤其是卡顿出现在应用转换时(会被记录在错误报告中)。错误报告还可以指出系统在什么时间会大范围出错,因而可能会减少其有效容量(如温控调频或内存碎片)。

使用 TouchLatency

一些不良行为的示例来自于 TouchLatency,它是用于 Pixel 和 Pixel XL 的首选周期性工作负载。它位于 frameworks/base/tests/TouchLatency,具有两种模式:触摸延迟和弹力球(要切换模式,请点击右上角的按钮)。

弹力球测试就跟看上去一样简单:无论用户输入什么内容,球都会一直在屏幕上弹跳。这通常也是目前为止最难完美运行的测试,不过,越接近在没有丢帧的情况下运行,就说明您的设备越好。弹力球测试很难执行,因为它是以很低的时钟频率运行的琐碎但完全一致的工作负载(此时假设设备配有频率调节器;不过,如果设备是以固定的时钟频率运行,则在首次运行弹力球测试时将 CPU/GPU 降频到接近最小值)。当系统静止且时钟频率降至接近空闲时,每帧所需的 CPU/GPU 时间增加。您可以查看球以及卡顿的对象,还可以在 systrace 中查看丢失的帧。

因为工作负载非常一致,所以您可以通过在每个丢失的帧期间跟踪系统上正在运行的工作负载(而非界面通道)来确定大多数抖动源,这比在用户可见的大多数工作负载中确定抖动源要容易得多。较低的时钟频率会使任何抖动都更有可能造成丢帧,从而放大抖动的效果。因此,TouchLatency 越接近 60 帧/秒,您在较大的应用中遇到导致时有时无且难以重现的卡顿的不良系统行为的可能性越小。

由于抖动通常(但不总是)时钟速度不变,因此请使用以非常低的时钟速度运行的测试来诊断抖动,原因如下:

  • 并非所有抖动都是时钟速度不变,很多抖动源仅占用 CPU 时间。
  • 频率调节器应通过降频获取接近截止时间的平均帧时间,这样运行非界面任务所花费的时间可将其推过丢帧的边缘。