本文基于 Session 10077 - Eliminate animation hitches with XCTest
概述
iOS中动画无处不在,应用中优雅流畅的动画可以显著提升用户体验,同理卡顿也会影响用户体验。通过这个 WWDC Session,我们将学会如何通过 XCTest 来检测滑动和动画过程中的掉帧,进而在开发阶段就能解决问题,避免糟糕的用户体验。
如何定义卡顿(Hitches)
当用户在页面上操作时,比如上下滑或者点击导航栏上的返回按钮时,主要焦点集中在手势的交互上。良好的交互体验是提供“众享丝滑”的响应速度,反之用户将会感知到明显的卡顿。我们将这些用户可感知的“抖动”称之为卡顿(Hitches),卡顿是指某一帧画面的显示比预期要晚。卡顿会影响用户体验,甚至让用户失去对应用的兴趣(即卸载🐶)。

如图所示,我们可以逐帧来看动画过程,当我们缓慢移动时,前2帧按预期显示在屏幕上,滑动很流畅且是“跟手”的,但是第3帧停留在屏幕上的时间超出预期,滑动不再“跟手”,第4帧出现时,列表出现了一次跳变,然后滑动再次变得“跟手”。
渲染原理
为了搞清楚为什么会出现上面的状况,我们首先来看看画面是如何展示到屏幕上的。iPhone 或 iPad 上的帧率一般都是60,即刷新频率为60赫兹,每帧耗时16.67毫秒,但是在 iPad Pro 的刷新频率为120赫兹,即每帧耗时8.33毫秒。垂直同步信号决定了是否需要切换当前显示的帧,当某一即将要显示的视频帧在垂直同步信号来临的时候没有显示,就发生了卡顿,卡顿的严重程度取决于那一帧延迟了多久才展示,拿上图为例,第4帧延迟了16.67毫秒才展示到屏幕上。
更多介绍推荐参看 《iOS 保持界面流畅的技巧》。
量化卡顿
有两种方式可以量化卡顿:
- 1.卡顿时间:某一帧比预期展示的时间晚了多少毫秒
- 2.卡顿率:总的卡顿时间/总时间
听起来可能比较复杂,这里为什么不是直接用掉帧或者掉帧率来表述呢?因为帧率太绝对,容易造成误解。如果测试过程除了动画外还有其他(闲置)阶段,那么 FPS 的意义就没有那么大,因为闲置期间我们本身就不希望画面会变换,同时一些情况下,我们也会设置一些低于最大 FPS 的帧率,比如一些游戏的帧率是每秒30帧,视频的帧率是每秒24帧。拿iOS系统的时钟应用为例,考虑到性能及电池损耗,icon 上的指针的帧率为10。
卡顿时间通常情况下是不可比较的,1秒内总的卡顿时间和10秒内的总的卡顿时间是没有可比性的。
我们可以通过统一卡顿率(即测试阶段每秒的卡顿时间)来制定一些度量标准来对比不同测试的场景,然后得出大概的用户影响情况。
标准推荐
苹果推荐使用以下几个值来定义对用户体验的影响程度:

程度 |
标准值 |
严重 |
每秒钟卡顿超过10毫秒,严重影响用户体验需要立即解决 |
警告 |
每秒钟卡顿在5~10毫秒之间,用户可能会察觉,需要开始介入排查 |
良好 |
每秒钟卡顿小于5毫秒,继续保持 |
度量及优化
从 iOS14 开始,开发者可以在开发及线上阶段均可使用系统提供的 XCTest 框架来排查动画的卡顿。在单元测试和 UI 测试中可以使用 XCTest 来收集动画相关数据及卡顿信息,同时可以使用 MetricKit 收集线上用户卡顿数据,然后结合 Xcode Organizer 来做性能分析。

这个 Session 主要关注开发阶段如何使用 XCTest 性能测试来捕获卡顿,想要了解如何查看线上用户的卡顿信息可以翻看另外两个 Session。

WWDC20 10081-What's New in MetricKit
WWDC20 10076-Diagnose Performance Issues with the Xcode Origanizer
在 Xcode 11 中苹果引入了 XCTMetrics 来帮助开发者衡量一些系统性能数据,比如耗时、CPU 使用率、内存占用、os_signpost 打点以及存储。

Xcode 12 引入了一项独立的启动耗时的衡量标准 XCTApplicationLaunchMetric
,同时也新增了一些模板供开发者来制定自己的性能衡量标准。
👉点击查看新增API
```objc
@interface XCTOSSignpostMetric (XCTBuiltinOSSignposts)
/*!
- @property navigationTransitionMetric
- The XCTMetric object covering navigation transitions between views
*/
@property (readonly, class) id navigationTransitionMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property customNavigationTransitionMetric
- The XCTMetric object covering custom navigation transitions between views
*/
@property (readonly, class) id customNavigationTransitionMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property scrollDecelerationMetric
- The XCTMetric object covering scroll deceleration animations
*/
@property (readonly, class) id scrollDecelerationMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property scrollDraggingMetric
- The XCTMetric object covering scroll dragging animations
*/
@property (readonly, class) id scrollDraggingMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
@end
/*!
- @class XCTApplicationLaunchMetric
- A metric which measures application launch durations.
*/
API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0))
__attribute__((objc_subclassing_restricted))
@interface XCTApplicationLaunchMetric : NSObject
/*!
本文基于 Session 10077 - Eliminate animation hitches with XCTest
概述
iOS中动画无处不在,应用中优雅流畅的动画可以显著提升用户体验,同理卡顿也会影响用户体验。通过这个 WWDC Session,我们将学会如何通过 XCTest 来检测滑动和动画过程中的掉帧,进而在开发阶段就能解决问题,避免糟糕的用户体验。
如何定义卡顿(Hitches)
当用户在页面上操作时,比如上下滑或者点击导航栏上的返回按钮时,主要焦点集中在手势的交互上。良好的交互体验是提供“众享丝滑”的响应速度,反之用户将会感知到明显的卡顿。我们将这些用户可感知的“抖动”称之为卡顿(Hitches),卡顿是指某一帧画面的显示比预期要晚。卡顿会影响用户体验,甚至让用户失去对应用的兴趣(即卸载🐶)。

如图所示,我们可以逐帧来看动画过程,当我们缓慢移动时,前2帧按预期显示在屏幕上,滑动很流畅且是“跟手”的,但是第3帧停留在屏幕上的时间超出预期,滑动不再“跟手”,第4帧出现时,列表出现了一次跳变,然后滑动再次变得“跟手”。
渲染原理
为了搞清楚为什么会出现上面的状况,我们首先来看看画面是如何展示到屏幕上的。iPhone 或 iPad 上的帧率一般都是60,即刷新频率为60赫兹,每帧耗时16.67毫秒,但是在 iPad Pro 的刷新频率为120赫兹,即每帧耗时8.33毫秒。垂直同步信号决定了是否需要切换当前显示的帧,当某一即将要显示的视频帧在垂直同步信号来临的时候没有显示,就发生了卡顿,卡顿的严重程度取决于那一帧延迟了多久才展示,拿上图为例,第4帧延迟了16.67毫秒才展示到屏幕上。
更多介绍推荐参看 《iOS 保持界面流畅的技巧》。
量化卡顿
有两种方式可以量化卡顿:
- 1.卡顿时间:某一帧比预期展示的时间晚了多少毫秒
- 2.卡顿率:总的卡顿时间/总时间
听起来可能比较复杂,这里为什么不是直接用掉帧或者掉帧率来表述呢?因为帧率太绝对,容易造成误解。如果测试过程除了动画外还有其他(闲置)阶段,那么 FPS 的意义就没有那么大,因为闲置期间我们本身就不希望画面会变换,同时一些情况下,我们也会设置一些低于最大 FPS 的帧率,比如一些游戏的帧率是每秒30帧,视频的帧率是每秒24帧。拿iOS系统的时钟应用为例,考虑到性能及电池损耗,icon 上的指针的帧率为10。
卡顿时间通常情况下是不可比较的,1秒内总的卡顿时间和10秒内的总的卡顿时间是没有可比性的。
我们可以通过统一卡顿率(即测试阶段每秒的卡顿时间)来制定一些度量标准来对比不同测试的场景,然后得出大概的用户影响情况。
标准推荐
苹果推荐使用以下几个值来定义对用户体验的影响程度:

程度 |
标准值 |
严重 |
每秒钟卡顿超过10毫秒,严重影响用户体验需要立即解决 |
警告 |
每秒钟卡顿在5~10毫秒之间,用户可能会察觉,需要开始介入排查 |
良好 |
每秒钟卡顿小于5毫秒,继续保持 |
度量及优化
从 iOS14 开始,开发者可以在开发及线上阶段均可使用系统提供的 XCTest 框架来排查动画的卡顿。在单元测试和 UI 测试中可以使用 XCTest 来收集动画相关数据及卡顿信息,同时可以使用 MetricKit 收集线上用户卡顿数据,然后结合 Xcode Organizer 来做性能分析。

这个 Session 主要关注开发阶段如何使用 XCTest 性能测试来捕获卡顿,想要了解如何查看线上用户的卡顿信息可以翻看另外两个 Session。

WWDC20 10081-What's New in MetricKit
WWDC20 10076-Diagnose Performance Issues with the Xcode Origanizer
在 Xcode 11 中苹果引入了 XCTMetrics 来帮助开发者衡量一些系统性能数据,比如耗时、CPU 使用率、内存占用、os_signpost 打点以及存储。

Xcode 12 引入了一项独立的启动耗时的衡量标准 XCTApplicationLaunchMetric
,同时也新增了一些模板供开发者来制定自己的性能衡量标准。
👉点击查看新增API
```objc
@interface XCTOSSignpostMetric (XCTBuiltinOSSignposts)
/*!
- @property navigationTransitionMetric
- The XCTMetric object covering navigation transitions between views
*/
@property (readonly, class) id navigationTransitionMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property customNavigationTransitionMetric
- The XCTMetric object covering custom navigation transitions between views
*/
@property (readonly, class) id customNavigationTransitionMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property scrollDecelerationMetric
- The XCTMetric object covering scroll deceleration animations
*/
@property (readonly, class) id scrollDecelerationMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property scrollDraggingMetric
- The XCTMetric object covering scroll dragging animations
*/
@property (readonly, class) id scrollDraggingMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
@end
/*!
- @class XCTApplicationLaunchMetric
- A metric which measures application launch durations.
*/
API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0))
__attribute__((objc_subclassing_restricted))
@interface XCTApplicationLaunchMetric : NSObject
/*!
本文基于 Session 10077 - Eliminate animation hitches with XCTest
概述
iOS中动画无处不在,应用中优雅流畅的动画可以显著提升用户体验,同理卡顿也会影响用户体验。通过这个 WWDC Session,我们将学会如何通过 XCTest 来检测滑动和动画过程中的掉帧,进而在开发阶段就能解决问题,避免糟糕的用户体验。
如何定义卡顿(Hitches)
当用户在页面上操作时,比如上下滑或者点击导航栏上的返回按钮时,主要焦点集中在手势的交互上。良好的交互体验是提供“众享丝滑”的响应速度,反之用户将会感知到明显的卡顿。我们将这些用户可感知的“抖动”称之为卡顿(Hitches),卡顿是指某一帧画面的显示比预期要晚。卡顿会影响用户体验,甚至让用户失去对应用的兴趣(即卸载🐶)。

如图所示,我们可以逐帧来看动画过程,当我们缓慢移动时,前2帧按预期显示在屏幕上,滑动很流畅且是“跟手”的,但是第3帧停留在屏幕上的时间超出预期,滑动不再“跟手”,第4帧出现时,列表出现了一次跳变,然后滑动再次变得“跟手”。
渲染原理
为了搞清楚为什么会出现上面的状况,我们首先来看看画面是如何展示到屏幕上的。iPhone 或 iPad 上的帧率一般都是60,即刷新频率为60赫兹,每帧耗时16.67毫秒,但是在 iPad Pro 的刷新频率为120赫兹,即每帧耗时8.33毫秒。垂直同步信号决定了是否需要切换当前显示的帧,当某一即将要显示的视频帧在垂直同步信号来临的时候没有显示,就发生了卡顿,卡顿的严重程度取决于那一帧延迟了多久才展示,拿上图为例,第4帧延迟了16.67毫秒才展示到屏幕上。
更多介绍推荐参看 《iOS 保持界面流畅的技巧》。
量化卡顿
有两种方式可以量化卡顿:
- 1.卡顿时间:某一帧比预期展示的时间晚了多少毫秒
- 2.卡顿率:总的卡顿时间/总时间
听起来可能比较复杂,这里为什么不是直接用掉帧或者掉帧率来表述呢?因为帧率太绝对,容易造成误解。如果测试过程除了动画外还有其他(闲置)阶段,那么 FPS 的意义就没有那么大,因为闲置期间我们本身就不希望画面会变换,同时一些情况下,我们也会设置一些低于最大 FPS 的帧率,比如一些游戏的帧率是每秒30帧,视频的帧率是每秒24帧。拿iOS系统的时钟应用为例,考虑到性能及电池损耗,icon 上的指针的帧率为10。
卡顿时间通常情况下是不可比较的,1秒内总的卡顿时间和10秒内的总的卡顿时间是没有可比性的。
我们可以通过统一卡顿率(即测试阶段每秒的卡顿时间)来制定一些度量标准来对比不同测试的场景,然后得出大概的用户影响情况。
标准推荐
苹果推荐使用以下几个值来定义对用户体验的影响程度:

程度 |
标准值 |
严重 |
每秒钟卡顿超过10毫秒,严重影响用户体验需要立即解决 |
警告 |
每秒钟卡顿在5~10毫秒之间,用户可能会察觉,需要开始介入排查 |
良好 |
每秒钟卡顿小于5毫秒,继续保持 |
度量及优化
从 iOS14 开始,开发者可以在开发及线上阶段均可使用系统提供的 XCTest 框架来排查动画的卡顿。在单元测试和 UI 测试中可以使用 XCTest 来收集动画相关数据及卡顿信息,同时可以使用 MetricKit 收集线上用户卡顿数据,然后结合 Xcode Organizer 来做性能分析。

这个 Session 主要关注开发阶段如何使用 XCTest 性能测试来捕获卡顿,想要了解如何查看线上用户的卡顿信息可以翻看另外两个 Session。

WWDC20 10081-What's New in MetricKit
WWDC20 10076-Diagnose Performance Issues with the Xcode Origanizer
在 Xcode 11 中苹果引入了 XCTMetrics 来帮助开发者衡量一些系统性能数据,比如耗时、CPU 使用率、内存占用、os_signpost 打点以及存储。

Xcode 12 引入了一项独立的启动耗时的衡量标准 XCTApplicationLaunchMetric
,同时也新增了一些模板供开发者来制定自己的性能衡量标准。
👉点击查看新增API
```objc
@interface XCTOSSignpostMetric (XCTBuiltinOSSignposts)
/*!
- @property navigationTransitionMetric
- The XCTMetric object covering navigation transitions between views
*/
@property (readonly, class) id navigationTransitionMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property customNavigationTransitionMetric
- The XCTMetric object covering custom navigation transitions between views
*/
@property (readonly, class) id customNavigationTransitionMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property scrollDecelerationMetric
- The XCTMetric object covering scroll deceleration animations
*/
@property (readonly, class) id scrollDecelerationMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
/*!
- @property scrollDraggingMetric
- The XCTMetric object covering scroll dragging animations
*/
@property (readonly, class) id scrollDraggingMetric API_AVAILABLE(ios(14.0), tvos(14.0)) API_UNAVAILABLE(macos);
@end
/*!
- @class XCTApplicationLaunchMetric
- A metric which measures application launch durations.
*/
API_AVAILABLE(macos(10.15), ios(13.0), tvos(13.0))
__attribute__((objc_subclassing_restricted))
@interface XCTApplicationLaunchMetric : NSObject
/*!