APP终极性能生存指南

·  阅读 4100
APP终极性能生存指南

性能是客户端永远绕不开的话题,一起来康康今年的WWDC提供了哪些有关性能提升的建议吧~

(温馨提示:本片内容来源自WWDC21:Ultimate application performance survival guide

想了解更多WWDC2021内容的小伙伴,可以阅读我以下文章,欢迎多多交流和指正

检测和诊断内存问题

一文带你读完WWDC21核心(新)技术点

  • 使用的五种工具

    • Xcode Organizer
    • MetricKit
    • Instruments
    • XCTest
    • App Store Connect API
  • 参考的八个性能指标

    2.png

    • 电量

    • 启动时间

    • 超时响应率(Hang rate)

      APP无法响应用户的输入或者行为超过250ms,即记作一个hang

    • 内存

    • 磁盘写入

    • 滚动卡顿

    • APP终止

    • MXSignposts

  • 电量(battery usage)

    • 优化电池使用需要关注的几点:

      • CPU
      • 网络
      • 定位
      • 音频
      • 蓝牙
      • GPU

      其中CPU、网络、定位是电量消耗大户

    • 使用Xcode工具查看Debug期间的电量损耗情况

      4.png

      • 查看CPU超过20%的阶段(CPU High Utilization)
      • 查看CPU从闲置被唤醒的阶段(CPU Wake Overhead)

      5.png

    • 使用Instrument中的Time Profile工具查看该阶段更详细的信息

      (比如使用Location Energy Model确保应用如预期中正确地使用定位功能)

      6.png

    • 使用MetricKit收集用户的性能数据

      7.png

        // 创建遵守`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可以更具针对性的对某一用户在一段时间内的性能表现进行分析。

    8.png

    • 查看用户的电量使用情况

    9.png

    • Regressions

      Regressions是Xcode 13新增的模块,它将各个版本的性能指标中发生劣化的情况单独拎出来展示,让开发者更清晰的看到哪些性能指标亟待优化。

      10.png

    • 查看问题发生时对应的代码

      11.png

  • 超时响应率和滚动卡顿(Hang rate & Scrolling)

    • 超时响应

      长时间无法响应是导致用户强退应用的重要原因

    • 滚动卡顿

      当在下一次屏幕刷新时,新的内容还未ready就会出现卡顿

    Hang rate & Scrollings是表明APP没有及时响应的两个指标,一旦发生会严重影响用户体验,甚至让用户在使用应用时产生挫败感,从而降低用户的使用APP的意愿。

    • 使用Xcode Organizer查看线上的卡顿情况

      • Hang rate

      12.png

      • Scrolling

      13.png

    • 使用Instrument进行分析

      14.png

      • 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仍是每天上报一次性能报告,但是当诊断报告发生时,会立刻进行回调。

      The system then delivers metric reports at most once per day, and diagnostic reports immediately in iOS 15 and later and macOS 12 and later.

      // 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,可以用来监控关键代码的运行情况
    
    复制代码

15.png

  • 磁盘写入

    • 使用Instrument中的File Activity查看磁盘写入情况

      16.png

      • 优化建议:

        • 对于频繁写入的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查看线上磁盘写入情况

      17.png

      • 查看在Disk Writes报告中可以查看24小时内写入量超过1GB的case

      18.png

      • 在Xcode 13中,还可以得到一些优化建议

      19.png

    • 使用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查看线上启动数据

      20.png

      • 查看因启动超时导致的程序终止

      21.png

    • 使用Instrument中的App Launch工具进一步分析

      22.png

  • Memory

    • 使用Xcode Organizer查看线上内存使用情况

      23.png

    • 使用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

Identify trends with Power and Performance API WWDC20

Getting started with Instruments WWDC19

分类:
iOS
标签:
分类:
iOS
标签:
收藏成功!
已添加到「」, 点击更改