背景
某周五临近下班时,领导的头像突然晃动了起来...
本文为曾经开发工具的介绍...仅作为自己的总结
- (本文)TTI 页面可交互时间监控
- Flutter FPS 监控(待填坑)
- 颜色标尺(待填坑)
- 组件抓手(待填坑)
- 录屏分析
- 调试工具重构(待填坑)
TTI指标介绍
页面可交互时间是衡量用户体验的重要指标之一,一个页面打开速度越快,用户等待越少体验越好,业务流程进展也就越快。对 TTI 进行准确有效的监控可作为性能分析重要的指标之一。
方案确定
调研的同事在 Android 和 Flutter 侧均采用的是渲染比例的方法,当页面渲染达到一定比例时即判定页面可交互。笔者询问道:
- 页面push到完全铺满整个页面,页面渲染达标的判断依据是什么?
- 对于类似某些页面存在部分信息骨架屏的场景,如何兼容?
得到的回答是“取左上角和右下角存在填充数据的组件所构成的矩形占屏幕的比例”
进一步追问道:“如果页面数据展示很少呢?或者就这两个组件有值呢?或者存在带数据的骨架屏呢?或者....”
同事以“已开发完成”为由拒绝继续沟通 :)
显然,这套方案缺陷非常明显...并不适合......
问题分析
将指标特点拆分来看
a. 主流程接口已请求完成,骨架屏已消失
b. 页面已填充信息的组件达到一定比例
c. 存在特殊页面需要单独处理
方案选择
在确定采用填充率之前,需要考虑三个主要的问题及其应对草案:
Q1: 页面交互判断标准如何界定?
A1: 页面出现到可交互状态,页面变化最大的就是页面信息的填充占比。以页面初次展示为始,信息展示模块填充信息是否超过阈值为最终的判断标准
Q2: 如何兼顾方案的可实施性、运行性能?
A2: 依赖页面生命周期判定起始时间,TTI的监听状态来控制整个监听周期,同时通过控制样本数量&类型&阈值配置&超时时间以达到性能的可控
Q3: 如何确保功能的独立性,保障未来的扩展性
A3: 利用协议约束单个指标监听方案的接入规范
贴一下在调研各方案时的对比:
方案名 | 方案描述 | 侵入性 | 性能 | 通用性 | 订制化 | 结论 |
---|---|---|---|---|---|---|
打点 | 通过业务打点上传 | 高 | 高 | 低 | 低 | ❌ 仅适用于业务分析 |
截图 | 通过直方图分析截屏判断是否一致 | 无 | 低 | 高 | 低 | ❌ 仅适用Debug模式 |
渲染比例 | 坚挺页面控件软件面积比例 | 小 | 高 | 中 | 中 | ❌ 不适用iOS,边界场景覆盖复杂 |
填充率 | 监听页面信息类组件的填充比例 | 小 | 高 | 高 | 高 | ✅ 适用 |
整体结构
主要功能点
监控的周期
- 通过切面编程实现生命周期的HOOK,以viewDidLoad为开始时间,达到可交互状态为终止时间,两者之差就是 TTI
- 当监控到页面可操作时监控结束,可主动结束(例如超时)
从图中可以看出,页面打开时常还可精细化为“启动时间”、“页面初始化时间”、“首次渲染耗时”、“二次渲染耗时”。而在实际的业务场景中, 页面init并不一定代表页面即将展示,系统启动页面的时间几乎可以忽略不计。
CADisplayLink
相对于 GCD Timer 而言更切合屏幕刷新的特点,避免过于频繁的循环。
广度优先搜索BFS
兼顾视图树的特点, 利用广度优先搜索的特点可以尽可能大的覆盖页面区域。当然,在BFS的基础上需要对TTI判定的提点进行微调(见样本取样介绍)
样本取样
结合BFS的尽可能大的覆盖页面区域的特点,仅需要取少量样本,例如采样前50个有效组件即可判断页面是否已达可交互状态。对于有效组件的定义,可指定两个特点:
1. 尽可能的靠近视图树结构的末端
页面的结构本质上可理解为一颗视图树,视图树中不仅包含了信息类的组件,还包含很多容器类的组件, 例如View、tableView、scrollView等等。这类容器类组件在 BFS 的搜索过程中可直接跳过,直接遍历其子节点。
2.可展示信息的组件
信息组件的样本取样可以过滤为最常见的信息组件,Label,ImageView,TextView,UIButton等, 下图为抓取样本中已填入信息的组件的示意图:
判空策略
判定信息类的组件是否有显示内容,例如Label的text
,ImageView的image
。
填充率阈值
当样本中的填充的组件数量超过阈值时即可表示达成了可交互状态,笔者的预设的缺省值为50%。少数特殊页面可通过页面阈值配置予以兼容。页面阈值的可配置化可使用后端配置下发,也可在前端对页面组件添加阈值属性(具体添加方式依项目情况而定,属性、协议都可行)
可配置化使得监控的标准可订制化,是TTI监控策略中比较重要的特性。
其他难点及解决方案
Q1: 同一指标不同监控方案侧重点不同如何兼顾?
A1: 简化外部调用,统一规范,通过配置来控制具体监控方案的调用
Q2: 如何降低监控本身带来的性能损耗
A2: 优化具体方案,明确监控的边界,加入AB开关容灾机制
Q3: 如何形成对应用的整体打开速度分析
A3: APP 内采集的数据,需要将数据上传至后端进行整合后按照时间输出打开速度的走势图
结语
打开时间包含了接口请求所消耗的时间,起到了前端对接口抖动的监控覆盖,同时也可用于“白屏监控”。开发过程中尽可能避免对业务的侵入,在监控TTI指标的过程中控制好阈值的配置,有效样本数量就可以在不影响性能的前提下获取到比较精准的时间。
后续更新
前段时间主流程最后一个页面也全部实现了预加载和骨架数据, 这就使得我们曾经去监控数据的填充一类的方式全部都失效了, 最终,这类初始状态就带有几乎全部数据填充的页面都改为使用纯业务打点的方式, 最准确,性能消耗也最小。这并不否定之前我们非侵入式的监控,这类页面仅占总数的很少部分,而业务打点也是当前最适合的方式。