您可以使用 Simpleperf 评估设备的性能。Simpleperf 是一款适用于 Android 平台上的应用和本机进程的原生分析工具。您可以使用 CPU 性能分析器 实时检查应用的 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 是 384 MHz 还是 2 GHz,所需时间都是固定的。涉及抖动时,增加容量并非提升性能的可行解决方案。因此,在受抖动限制的情况下,速度更快的处理器通常不会提升性能。
最后,与容量不同的是,抖动几乎完全存在于系统供应商的网域中。
内存消耗
一直以来,人们都将性能不佳归因于内存消耗。虽然消耗本身不是性能问题,但是它可能会通过 lowmemorykiller 开销、服务重启和页面缓存颠簸引起抖动。减少内存消耗可以避免导致性能不佳的直接原因,但是还有其他可避免这些原因的具有针对性的改进(如固定框架以防止在不久之后进行的分页过程中将其分出)。
分析初始设备性能
从运行正常但性能不佳的系统开始,并尝试通过查看用户可见的糟糕性能的每个个案来修复系统的行为,这种做法并非良策。因为性能不佳情况通常不易重现(如抖动)或者由应用问题导致,整个系统中可阻止此策略发挥作用的变量非常多。因此,很容易错误地识别原因并做出微小的改进,而错失修复整个系统性能的系统性机会。
相反,在启动新设备时,请使用以下常规方法:
- 使系统启动到所有驱动程序都会运行并包含一些基本频率调节器设置的界面(如果更改频率调节器设置,请重复以下所有步骤)。
- 确保内核支持
sched_blocked_reason
跟踪点以及显示通道中表示何时将帧发送到显示屏的其他跟踪点。 - 在运行轻量级的一致性工作负载(例如,UiBench 或 TouchLatency) 中的球测试)的同时,对整个界面通道(从通过 IRQ 接收输入到最终的扫描输出)进行长时间的跟踪。
- 修复在轻量级的一致性工作负载中检测到的丢帧问题。
- 重复执行第 3-4 步,直到您可以在零丢帧的情况下一次运行 20 秒以上的时间。
- 转向用户可见的其他卡顿源。
您可以在设备启动早期执行的其他简单操作包括:
- 确保您的内核有 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 个百分位帧时间等)中的类似差异不相关。合成基准属于仅限容量的基准;抖动仅可以从基准的批量操作中窃取时间来影响这些基准衡量的性能。因此,合成基准得分在作为用户可察觉的性能的指标时是最不相关的指标。
考虑两种运行可渲染 1000 帧界面的基准 X 的 SOC,并报告总渲染时间(得分越低越好)。
- SOC 1 在 10 毫秒内渲染每帧基准 X,得分为 10,000。
- SoC 2 在 1 毫秒内渲染 99% 的帧,但是在 100 毫秒内渲染 1% 的帧,得分为 19,900,得分明显较好。
如果基准代表实际的界面性能,则 SoC 2 将无法使用。假设刷新率为 60 Hz,SoC 2 在每 1.5 秒的操作内将出现一次卡顿帧。与此同时,SoC 1(根据基准 X 得出的较慢的 SoC)将会非常流畅。
使用 bug 报告
bug 报告有时对于性能分析非常有用,但是因为这类报告本身就耗费资源,因此对于调试时有时无的卡顿问题用处不大。bug 报告可能会提供一些线索,告诉您系统在给定的时间正在执行什么操作,尤其是卡顿出现在应用转换时(会记录在 bug 报告中)。错误报告还可以指出系统在什么时间会大范围出错,因而可能会减少其有效容量(如温控调频或内存碎片)。
使用 TouchLatency
一些不良行为的示例来自于 TouchLatency,它是用于 Pixel 和 Pixel XL 的首选周期性工作负载。它位于 frameworks/base/tests/TouchLatency
,具有两种模式:轻触延迟和弹力球(如需切换模式,请点击右上角的按钮)。
弹力球测试就跟看上去一样简单:无论用户输入什么内容,球都会一直在屏幕上弹跳。这通常也是目前为止最难完美运行的测试,不过,越接近不丢帧的运行效果,就说明您的设备越好。弹力球测试很难执行,因为它是以很低的时钟频率运行的琐碎但完全一致的工作负载(此时假设设备配有频率调节器;不过,如果设备是以固定的时钟频率运行,在首次运行弹力球测试时将 CPU/GPU 降频到接近最小值)。当系统静止且时钟频率降至接近空闲时,每帧所需的 CPU/GPU 时间增加。您可以查看球以及卡顿现象,还可以在 systrace 中查看丢失的帧。
因为工作负载非常一致,所以您可以通过在每个丢失的帧期间跟踪系统上正在运行的工作负载(而非界面通道)来确定大多数抖动源,这比在用户可见的大多数工作负载中确定抖动源要容易得多。较低的时钟频率会使任何抖动都更有可能造成丢帧,从而放大抖动的效果。因此,TouchLatency 越接近 60 帧/秒,您在较大的应用中遇到导致时有时无且难以重现的卡顿的不良系统行为的可能性越小。
由于抖动通常(但不总是)时钟速度不变,请使用以非常低的时钟速度运行的测试来诊断抖动,原因如下:
- 并非所有抖动都是时钟速度不变,很多来源仅占用 CPU 时间。
- 频率调节器应通过降频获取接近截止时间的平均帧时间,这样运行非界面任务所花费的时间可将其推过丢帧的边缘。