背景介绍
关键字: iOS 性能测试 质量保证明 QA 启动时间
无论是竞品对比、还是公司内部的多个产品的横向比较、某产品的 App 在版本之间的性能监控,都需要有一种标准来衡量性能表现,比如本文要讲述的启动时间。
从点击 App 图标开始,计算到画面渲染个差不多的时候(谜一样的定义),通过高速时间戳录制,来做差计算一个值,成为某版本的启动性能指标。该方法的定义模糊性加上不同人员的操作不可控性,导致测量结果基本无意义,或者说这样的误差已经大于性能发生变化的单位值了,开发也不会信服这样的度量结果。
总之:要度量性能,不要估计性能。 (from WWDC)
之前基于 Instruments 逆向的一些路又弯又长,看到官方发布度量标准简直感激涕零。
WWDC 2019 发布了 XCTest Metrics 相关的一些工具,助力开发者度量 App 的性能。包括 XCTest Metrics, MetricKit, Xcode Metrics Orgnizer. 它们分别针对软件产品的开发、测试、上线等不同阶段进行性能度量。本文首先分享下我本次对于 iOS App 启动过程的学习心得,欢迎大家批评指正。
在 Xcode 11 集成的功能中,菜单栏 Window - Organizer 可以找到下图界面,这里对于 App 的启动时间做了一个条形图展示。
可以看到在 Launch Time 这个标题下面有一行小字:
Time to first frame
意思是展示的时间表示截止到 App 画面的第一帧渲染的时间。这里涉及到一个渲染过程,我们简单看下 WWDC 2019 上展示的 App 启动阶段分析:
官方 Keynote 十分用心,不同阶段使用不同颜色对应表示,一目了然。可以看到在 400 ms 结束的时候,有一个 Initial Frame Render 过程结束了。App 运行的过程就是一个无限循环的过程(Runloop),每秒 60 帧的流畅定义就是基于这个 frame 的值产生的。当我们 App 绘制出界面的第一帧的时候,其实 App 的整个初始化的过程就完成了。官方基于此开发 Launch Time 性能度量工具。
为什么画面开始渲染的时候就能停止启动性能的度量了呢?
我们来看下这张图:
在 Extend 阶段中,App 已经是可交互、有响应、开始显示异步加载的一些网络数据的状态了。比如首页的 Feed 流中的图片列表,可以使用 SDWebimage 等第三方框架进行异步加载。但是这个异步过程与启动过程应当是分开的。
来考虑这样一个场景:
- 给 iPhone 网络限速为 5kb/s, 此时首次打开新闻类 App 花费了 30 s 才将所有画面加载完,此时能说启动花费了半分钟么?
- 另一个例子,打开一个复杂市区的百度地图场景,前 3 秒出现了主干道路,然后又花费了 5 秒获取到了各种小路和店铺等各种信息。
XCTest Metrics 的基本使用
结果 - 使用小米家庭 App 做个 Demo
通过 xcodebuild 命令行输出和 Xcode 界面运行 XCTest,都可以看到启动时间的运行结果。
XCTest Metrics 测量结果为 0.443 s
下面是告诉时间戳的计算结果:
时间差:0.904 - 0.437 = 0.467 s
通过实验对比,发现从系统接收到用户的点击事件(图标变灰),到界面出现第一帧(而不是所有图片加载完),屏幕告诉时间戳计算的差值十分接近 XCTest Metrics 度量结果,仅存的误差应该是人眼判断的第一帧出现时间比实际的第一帧出现时间晚导致的。
通过集成到 Jenkins 可以完成自动化流程,并传入到前端汇总展示,撒花~
一些提示
- 启动时间要同时间对比新设备和旧设备。
- 可以开启飞行模式或者 mock 网络请求来测试启动性能。
- 不要更改 iCloud 账户,防止账户同步影响启动过程
- 尽量使用 App Store 等正式版本的安装包。
关于 App 启动方式
- 冷启动
将手机关机,静置2分钟。然后开机后启动某 App。该流程中 App 在内存中是没有初始进程的。 - 热启动
将 App 通过多任务界面杀掉,然后再次打开,依次循环操作。该流程中 App 部分内容是残留在内存中的。 - 恢复启动
按下 Home 按键将 App 放入后台,此时 App 完全在内存中存活,进程也正常存在,再次点击 App 图标。