简介
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