概述
应用卡顿是导致用户流失的重要原因之一,卡顿监控模块致力于协助用户治理卡顿问题。卡顿治理的一个重要思路是通过提取有效的指标衡量应用当前的状况,抓取足够的信息提供优化方向。卡顿监控模块通过 FPS 及挂起率两个指标来衡量应用的流畅度情况,通过卡顿问题监控,直接抓取卡顿堆栈,协助用户定位卡顿原因,为用户提供优化方向。
卡顿指标通过稳定、轻量的采集技术,收集应用在整个运行过程中的流畅度数据。
卡顿问题监控,通过高频抓栈技术,提供丰富的现场信息,实现准确归因。
Android 平台自研快速抓栈技术,对比传统抓栈实现,有效提升了性能。
无论是卡顿指标,还是卡顿问题,都支持用户自定义采样率,同时提供了丰富的数据分析能力。
指标
模块通过 FPS 及挂起率两个指标来衡量应用的流畅度情况。
FPS 数据以场景为粒度,直接统计用户上报的原始记录,在原始记录的基础上统计平均值和分位值。
挂起率则以用户上报的原始记录为基础,以设备 ID 进行按天聚合,一个设备一天中产生的多条记录被聚合成一条记录。挂起率是在这些聚合后的数据的基础上进行统计平均值和分位值。
FPS
FrameRate:帧率是 GPU 和 CPU 合作,在应用运行时可产生的图像的数量,计量单位是帧/秒(FramesPerSecond,FPS),通常是评估硬件性能与应用体验流畅度的指标。核心要点如下:
卡顿监控统计包含 UI 刷新的 FPS,反映了用户使用应用的真实感受。
终端性能监控 Pro 的卡顿监控统计的是包含真实 UI 刷新的 FPS,剔除了页面静止期间的数据。例如查看相册页面,如果应用没有处理好异步加载的话,在用户滑动时,可能比较卡顿。用户安静观看照片时,由于没有触发耗时操作,可能看起来一切正常。如果以用户停留页面总时长来统计 FPS,则页面无刷新的时间可能将滑动时的卡顿表现给平均掉了。使用终端性能监控 Pro 的卡顿指标监控,则没有这个问题,我们只统计包含页面真实刷新时 FPS,不会因为页面无刷新的时长变化而导致 FPS 变化。
平台通过对 FPS 数据进行归一化操作,兼容各种刷新频率。
当前市面上存在各种屏幕刷新率的手机,常见的是60Hz、90Hz、120Hz。简单来讲,如果一个应用性能非常好,UI 更新不耗时,那么其帧率是受屏幕刷新率限制的,其帧率不可能高于屏幕刷新率。也就是说,即使一个性能非常好的应用,在不同屏幕刷新率下,其帧率是不一样的。不同的屏幕刷新率最终影响 VSYNC 信号的产生频率如下图所示。

终端性能监控 Pro 采用归一化的思想,将不同屏幕刷新率统一归一到60Hz,也就是说,即使两台不同刷新率的手机,平台统计到的一款应用的 FPS 基本一致。
平台按场景统计 FPS,一次运行期间相同场景的数据会合并上报。
当前终端性能监控 Pro 是按场景来统计 FPS,在应用运行过程中,卡顿指标统计模块,统计每个场景的数据,用户切换场景后,统计模块会保存上一个场景的数据。在应用下次启动后,上报模块会提取上次运行期间所采集的数据,合并相同场景的数据,最终得到每个不同场景的数据记录。
支持统计多种分位值:P50、P90、P99,帮助用户更好理解用户真实体验。
场景数据记录上报到服务器,服务器会保存这些原始记录,同时统计平均值和分位值(P50 、P90 、P99)。
分位值(P50、P90、P99):
例如 A 应用的某次运行,用户体验了10个场景,产生10条记录上报到服务器。共有10个用户上报,总共产生了100条记录。每条记录都有 FPS,服务器将这100条记录按 FPS 的大小排序,从大到小排序。已排序数据中的第50个,即这批数据中的 P50;已排序数据中的第90个,即为这批数据中的 P90;已排序数据中的第99个,即为这批数据中的 P99。
在 FPS 中,分位值是按从大到小排序的,因此 P50 >= P90 >= P99 。
SDK 的 FPS 统计方式对应用的性能影响非常低。
挂起率
卡顿监控,对于挂起率的统计是,如果应用两帧之间的刷新延时超过200ms ,则认为此时应用不能很好地响应用户的交互,并且累加到挂起时间中。一个设备的挂起率,是指这个设备在一天中,总的挂起时间除以设备的前台总时长。也就是说,卡顿监控的挂起率是以设备、按天聚合统计的,计算公式为:设备挂起率 = 设备一天的累计挂起时间(单位是秒)/ 设备一天的前台总时长 (单位是小时)。

对于一个应用而言,我们关注的是设备挂起率的分位值,如 P50、P90、P99等。例如某个应用 A,在某天中,有100台设备上报了挂起率数据,则后台按设备 ID 聚合,得到100条记录,每条记录统计挂起率,这100条记录,从小到大排序。在已排序的数据中,第50个为45.23s/h,则 P50 = 45.23s/h,依次类推,第90个数据为134.23s/h,则 P90 = 134.23s/h。
指标分析
以下内容以 FPS 指标为例进行各种指标的分析说明,挂起率可参考以下内容。
趋势分析
用户可以在趋势分析中,查看一天,或者一段时间的 FPS 变化趋势。平台提供了平均值,分位值(P50 、P90 、P99)多种统计方式,帮助用户更好理解应用FPS 的整体状况。

用户可以查询指定条件下的 FPS 数据,如下图所示,指定场景的 FPS :

对比分析
在趋势分析中,我们可以将一组查询结果添加到对比列表中,添加多组查询结果后,后续可以在对比列表中,对比分析这两组数据。
如下图所示,我们期望对比分析两个不同场景的数据情况,分别查询这两个场景的数据,添加到对比列表中,单击趋势预览即可查看不同统计维度的对比结果。

趋势预览示例图:

多维分析
有些情况下,如果想查看一段时间、所有 App 版本,或者所有场景的数据情况,通过多维分析可以解决这个问题。

还支持分析指定版本,在某些场景下的数据情况。

问题监控
卡顿问题监控核心专注于帮助用户找到导致应用卡顿的原因,通过监控 UI 线程消息执行耗时,结合高频、连续抓栈策略,将耗时超过阈值的情况上报到服务器。服务器基于卡顿堆栈树,提取关键耗时特征,将个例聚合成 Issue(问题),得到卡顿问题列表。
问题列表
在卡顿 > 问题列表页面可查看卡顿问题监控的数据,支持对数据进行筛选和分析。
卡顿问题列表支持丰富的搜索条件,用户可以通过添加字段来自由设置期望展示的搜索字段。用户还可以通过展示筛选项与收起筛选项来调整搜索条件区域的展示效果,网页会记住用户的选择;
选定搜索条件后,单击查询提交查询任务,得到查询结果后,页面会自动刷新。
卡顿问题列表的头部包含查询结果的摘要信息,用户可以看到满足条件的问题有多少个,以及 Top N 问题的占比情况。
查询结果默认按 Issue 的上报时间排序,一个 Issue 包含问题特征、最近上报时间、卡顿耗时的平均值及分位值、关键堆栈耗时平均值及分位值、叶子结点最大耗时的分位值等,用户可以结合实际需要,通过设置自由选择字段展示。
用户单击 Issue 的问题 ID,可进入问题详情查看一个 Issue 的上报详情。
列表展示的统计字段比较多时,结果列表的内容比较宽,用户可以左右滑动来查看各部分内容。
用户还可以将本页的内容直接以表格的方式导出数据。

问题详情
问题详情分为问题头部、详情分析以及下钻分析三部分。
问题头部:包含 Issue 维度的描述,例如 Issue 的版本标签,用户给 Issue 打的自定义标签、处理状态、处理人、问题 ID 、问题特征等。
个例分析:侧重对卡顿个例进行分析,用户可以利用搜索条件,查询满足指定条件的个例。
下钻分析:侧重对整个 Issue 进行分析,包含趋势分析、统计分布、出错堆栈分析等。

个例分析
查看某个卡顿个例,可重点关注以下信息:
1. 优先查看卡顿总耗时、关键堆栈耗时,以及叶子结点最大耗时,该信息可以帮助我们快速判断卡顿的类型。
2. 接着,开始分析卡顿的堆栈详情。当前卡顿的堆栈现场通过三种不同的方式呈现:时间片、堆栈树、火焰图。
通常情况下,先分析火焰图,它比较直观呈现了卡顿现场的全貌。
接着利用时间片或者火焰图分析堆栈详情。
火焰图以及堆栈树中的耗时是通过抓栈间隔估算的结果。
卡顿耗时是准确的,表示一条 UI 线程的消息执行耗时。
卡顿耗时与卡顿堆栈耗时:
卡顿耗时表示一个 UI 线程的消息执行的耗时,是一个准确的值。卡顿堆栈的耗时是根据抓栈次数以及抓栈间隔估算得到。当前卡顿监控通过监控 UI 线程的消息执行耗时来判断应用是否发生了卡顿。

以下图示例,这个堆栈连续6帧都被抓中,当前的抓栈间隔是52ms,堆栈的耗时估算为52 x 6 = 312ms。
说明:
抓栈间隔:Android 与 iOS 机型,抓栈间隔可能都有差异,您可以结合时间片中显示的抓栈次数,再结合推算的抓栈耗时推算出本个例的抓栈间隔。
另外,用户还可以结合操作日志以及现场数据来进一步分析卡顿现场。

下钻分析
用户可以通过下钻分析来查看 Issue 的上报趋势,以及在一些字段的分布情况。
下钻分析支持用户设置搜索条件,查看指定条件下的统计结果。
上升趋势支持查看不同统计维度的数据,当前支持发生次数、影响用户数(按用户 ID 去重)、影响设备数(按设备 ID 去重)。支持查看不同聚合粒度下的数据,最小支持分钟级别。

统计分布是指查看搜索条件下,在指定字段的统计分布情况。
说明:
统计分布的有效上报指这个字段包含有效值的上报情况。有些情况下,某些字段可能存在取不到值,或者取的值不合法的情况。因此虽然搜索条件一致,有可能不同字段的有效上报次数不一致。
