APM - iOS 卡顿监控 Hang

3,734 阅读4分钟

简介

Hang

APP一段无响应的阶段,由于主线程忙于其他任务或者等待其他线程或者系统资源,导致视图内容更新延迟至少250ms

Main Loop

用户与设备进行交互,Runloop接收事件,处理事件,有需要的情况下更新UI,这些都发生在主线程runloop的一圈中

处理时间比较久的情况下,用户输入和UI更新之间就会产生延迟。更差的情况下,当hang发生的时候,事件被堆积起来而主线程无法处理

hang的影响在不同的场景下造成的影响也不同。通常超过1秒的延迟总是会被看成是hang,不过更短时间的延迟也会。比如在滑动过程中,0.5秒的延迟用户体验就很不好了,但是转场中就不会这么明显

Hang的原因

  • 主线程本身忙碌
    • 一个单次长任务
    • 多个短任务
  • 主线程被其他线程或者系统资源Block住

主线程忙碌

执行多余的工作

执行不相关的工作

主线程阻塞

I/O

主线程读取需要等待其他线程写入完成

Synchronization

主线程等待其他线程释放锁

获取不常变的数据

在存储器的层级上,在部分系统API的获取上,存在较大的速度差,这种情况下需要缓存数据,不能在主线程中反复获取这类不会经常变化的数据

获取联系人

访问系统资源

监控和诊断

  • 开发阶段可以使用Performance Checker,Instruments
  • Beta阶段可以开启设备上Hang检测,或者使用MetricKit
  • 发布后可以在Xcode Reports Organizer对Hang进行监控

开发阶段

System Trace

红线标识了系统调用,紫色图形标识了虚拟内存缺页,水平蓝色区域标识主线程正在忙碌。在Profile中找到对这4.7s阶段的主线程堆栈聚合

Time Profiler

iOS 16, Xcode 14

通过持续显示应用的调用栈,标识了应用当前正在执行的内容

Thread Performance Checker

iOS 16, Xcode 14

检测优先级反转和主线程执行非UI任务

Beta测试阶段

On-device hang detection

iOS 16, Xcode 14

在设置 > 开发者 > Hang检测中,阈值有250ms,500ms,1000ms,2000ms几个选项。提供了实时的Hang通知,支持在在开发者签名的包和TestFlight包中诊断

对于Hang的检测是在后台以最低优先级的任务运行,用于最低限度的最小化对性能的负载影响,如果系统处于忙碌状态的话,则执行得会更久一些。有新的诊断可用的时候,通知会展示出来

发布阶段

MetricKit

这个库可以收集来自单一用户在Beta或者线上发布的APP中非聚合的 hang率指标和诊断报告

此处发现在获取联系人的函数导致的hang的问题

Xcode Organizer

iOS 16, Xcode 14

在Organizer工具中可以看到按照app version,日期,iOS系统版本分布的图表化信息,其中包括率Hangs的相关指标

选择Hangs选项

其中也包括了关于Hang的堆栈信息详情,需要上传对应的符号表用户符号化堆栈信息

可以通过App Store Connect REST APIs来访问Xcode Organizer中的数据内容,这样可以更好的跟开发者自建的系统集成或者添加额外的分析

Xcode 13.2开始Xcode Organizer中可以接收到关于监控性能指标的通知,建议打开通知开关,可以更好的接收通知用于预警例如Hang指标突然增加的情况

消除Hang

减少主线程工作

Caches

由于不同层级存储器访问速度不同的问题,由其主线程或者他线程访问数据之后,缓存到高速访问存储器,之后主线程访问可以节约大量的时间

Observers

观察者这种方式可以让主线程只关心数据或状态的变化,而不用进行昂贵开销和按需计算

移除主线程工作

Asynchronous API

很多非关键的任务可以交给低优先级的线程完成,即使需要多花一些时间,主线程可以专注于其他关键任务

GCD

异步任务并行队列可以很好的释放主线程的资源,执行完成之后可以回主队列回主线程执行UI更新等操作

引用

Track down hangs with Xcode and on-device detection

Understand and eliminate hangs from your app

Apple Document Improving app responsiveness

Analyze hangs with Instruments

引申

WWDC16 - System Trace in depth

WWDC17 - Modernizing Grand Central Dispatch Usage

WWDC19 - Improving battery life and performance

WWDC20 - Identify trends with the Power and Performance API

WWDC21 - Diagnose Power and Performance regressions in your app