性能是客户端永远绕不开的话题,一起来康康今年的WWDC提供了哪些有关性能提升的建议吧~
(温馨提示:本片内容来源自WWDC21:Ultimate application performance survival guide)
想了解更多WWDC2021内容的小伙伴,可以阅读我以下文章,欢迎多多交流和指正
-
使用的五种工具
- Xcode Organizer
- MetricKit
- Instruments
- XCTest
- App Store Connect API
-
参考的八个性能指标
-
电量
-
启动时间
-
超时响应率(Hang rate)
APP无法响应用户的输入或者行为超过250ms,即记作一个hang
-
内存
-
磁盘写入
-
滚动卡顿
-
APP终止
-
MXSignposts
-
-
电量(battery usage)
-
优化电池使用需要关注的几点:
- CPU
- 网络
- 定位
- 音频
- 蓝牙
- GPU
其中CPU、网络、定位是电量消耗大户
-
使用Xcode工具查看Debug期间的电量损耗情况
- 查看CPU超过20%的阶段(CPU High Utilization)
- 查看CPU从闲置被唤醒的阶段(CPU Wake Overhead)
-
使用Instrument中的Time Profile工具查看该阶段更详细的信息
(比如使用Location Energy Model确保应用如预期中正确地使用定位功能)
-
使用MetricKit收集用户的性能数据
// 创建遵守`MXMetricManagerSubscriber`的协议的类AppMetrics class AppMetrics: MXMetricManagerSubscriber { init() { // 初始化时将AppMetrics加入到`MXMetricManager`单例中 let shared = MXMetricManager.shared shared.add(self) } deinit { // 销毁时进行移除 let shared = MXMetricManager.shared shared.remove(self) } // 处理每日的metrics func didReceive(_ payloads: [MXMetricPayload]) { } // 处理diagnostics func didReceive(_ payloads: [MXDiagnositcPayload]) { } } 复制代码
-
-
使用Xcode Organizer查看线上性能数据
Xcode Organizer对MetrixKit收集到的数据进行了聚合,忽略了单一用户的详细数据,展现的是整体的趋势;
而使用MetricKit可以更具针对性的对某一用户在一段时间内的性能表现进行分析。
- 查看用户的电量使用情况
-
Regressions
Regressions是Xcode 13新增的模块,它将各个版本的性能指标中发生劣化的情况单独拎出来展示,让开发者更清晰的看到哪些性能指标亟待优化。
-
查看问题发生时对应的代码
-
超时响应率和滚动卡顿(Hang rate & Scrolling)
-
超时响应
长时间无法响应是导致用户强退应用的重要原因
-
滚动卡顿
当在下一次屏幕刷新时,新的内容还未ready就会出现卡顿
Hang rate & Scrollings是表明APP没有及时响应的两个指标,一旦发生会严重影响用户体验,甚至让用户在使用应用时产生挫败感,从而降低用户的使用APP的意愿。
-
使用Xcode Organizer查看线上的卡顿情况
- Hang rate
- Scrolling
-
使用Instrument进行分析
-
Thread State Trace
可以查看线程被阻塞的详细情况
-
System Call Trace
可以查看系统函数调用的时机和时长
-
-
使用XCTest进行性能测试
func testScrollingAnimationPerformance() throws { app.launch() app.staticTexts["Meal Planner"].tap() let foodCollection = app.collectionViews.firstMatch // `measure`函数默认重复5次,可以通过option设置手动停止 let measureOptions = XCTMeasureOptions() measureOptions.invocationOptions = [.manuallyStop] // 开始measure measure(metrics: [XCTOSSignpostMetric.scrollDecelerationMetric], option: measureOptions) { // 滑动 foodCollection.swipeUP(velocity: .fast) // 停止measure stopMeasuring() // 重置状态 foodCollection.swipeDown(velocity: .fast) } } 复制代码
-
使用MetricKit收集线上数据
在iOS 14中,MetricKit会收集用户使用过程中发生的问题,然后每24小时集中上报一次。
在iOS 15和MacOS 12中,MetricKit仍是每天上报一次性能报告,但是当诊断报告发生时,会立刻进行回调。
// Receive daily metrics. func didReceive(_ payloads: [MXMetricPayload]) { // Process metrics. } // Receive diagnostics immediately when available. func didReceive(_ payloads: [MXDiagnosticPayload]) { // Process diagnostics. } 复制代码
-
iOS 15中MetricKit新增动画性能检测的API,能够记录动画期间详细的性能数据和卡顿情况
func startAnimating() { // 标记动画开始执行 mxSignpostAnimaitionIntervalBegin( log: MXMetricManager.makeLogHandle(category: "animation"_telemetry), name: "custom_animation") ) } func animationDidComplete() { // 标记动画结束 mxSignpost(OSSignpostType.end, log: MXMetricManager.makeLogHandle(category: "animation_telemetry"), name: "custom_animation") } 复制代码
> 注:MXSignpost是MetricKit中封装的API,可以用来监控关键代码的运行情况 复制代码
-
-
磁盘写入
-
使用Instrument中的File Activity查看磁盘写入情况
-
优化建议:
-
对于频繁写入的case,推荐使用Core Data
-
避免快速创建和删除文件
-
-
-
使用XCTest进行性能测试
func testSaveMeal() { let app = XCUIApplication() let options = XCTMeasureOptions() options.invocationOptions = [.manullyStart] // 检测下面代码运行时的磁盘写入情况 measure(metrics: [XCTStorageMetric(application: app)], options: options) { app.launch() startMeasuring() let firstCell = app.cells.firstMatch firstCell.buttons["Save meal"].firstMatch.tap() let savedButton = firstCell.buttons["Saved"].firshMatch XCTAssertTure(savedButton.waitForExistence(timeout: 2)) } } 复制代码
-
使用Xcode Organizer查看线上磁盘写入情况
- 查看在Disk Writes报告中可以查看24小时内写入量超过1GB的case
- 在Xcode 13中,还可以得到一些优化建议
-
使用MetricKit收集用户的磁盘写入情况
// 标记开始磁盘写入 func syncAllContentsToDB() { mxSignpost(OSSignpostType.begin, log:MXMetricManager.makeLogHandle(categroy: "diskWrite_telemetry"), name: "custom_diskWrites") // sync contents to database // 标记磁盘写入结束 mxSignpost(OSSignpostType.end, log:MXMetricManager.makeLogHandle(category: "diskWrite_telemetry"), name: "custom_diskWrites") } 复制代码
-
-
启动时间
-
使用Xcode Organizer查看线上启动数据
- 查看因启动超时导致的程序终止
-
使用Instrument中的App Launch工具进一步分析
-
-
Memory
-
使用Xcode Organizer查看线上内存使用情况
-
使用Instrument中的Leak、Allocations和VM Tracker三个模板
- Leak检测内存泄漏
- Allocations分析内存的生命周期
- VM Tracker展示虚拟内存空间的使用情况
-
使用MetricKit收集线上数据
func saveAppAssets() { mxSignpost(OSSignpostType.begin, log: MXMetricManager.makeLogHandle(category: "memory_telemetry"), name: "custom_memory") // save app metadata mxSignpost(OSSignpostType.end, log: MXMetricManger.makeLogHandle(category: "memory_telemetry"), name: "custom_memory") } 复制代码
-
更多有关电量优化的Session:
Improving battery life and performance WWDC19
Analyze HTTP traffic in Instruments WWDC 21
更多Hang优化的Session:
Understand and Eliminate Hangs from you app WWDC21
更多滚动优化的Session:
Explore UI animation hitches and the render loop WWDC20
Eliminate animation hitches with XCTest WWDC20
更多磁盘写入优化的Session:
Diagnose power and performance regressions in your app WWDC21
更多启动优化的Session:
Why is my app getting killed WWDC20
更多内存优化的Session:
Detect and diagnose memory issues
更多关于性能工具的Session:
Diagnose performance issues with Xcode Organizer WWDC20
What's new in MetricKit WWDC20