iOS卡顿监控方案汇总

FPS

CADisplayLink允许我们注册一个与刷新信号同步的回调处理。可以通过屏幕刷新机制来展示fps值。

问题:

  • 回调总是需要cpu空闲才能处理,无法及时采集调用栈信息。
  • 监听屏幕刷新会频繁唤醒 runloop,闲置状态下有一定的损耗

子线程Ping

使用子线程定时向主线程中仍入空任务,超过指定时间任务未被执行则判定为卡顿。

问题

  • ping之间存在漏查情况。
  • 会不停的唤醒主线程runloop,有一定损耗。

RunLoop

基于runloop检测,使用子线程实时检测runloop状态,执行超过指定时间则判定为卡顿。

问题:

  • 捕获到的卡顿堆栈,不一定是最耗时的任务。不过最耗时任务有较大的概率被捕获到。
  • 在一些复杂的页面下,卡顿的产生并不一定是某个耗时大任务,可能是由于多个耗时小任务共同作用。在这种case下,runloop检测方式很难帮助我们解决界面的卡顿问题。

hook objc_msgSend

借助fishhook对objc_msgSend、objc_msgSendSuper进行hook,在方法开始执行和结束执行插入代码,从而获取堆栈和每个方法的耗时。设置一定的阈值,将耗时方法提取出来。

问题:

扫描二维码关注公众号,回复: 13681504 查看本文章
  • 需要写汇编来进行hook,实现成本相对较高。
  • 插入的代码执行频率较高。可以通过一定手段进行优化
    • 只对主线程上的调用进行操作
    • 对有一定耗时的方法进行记录
    • 对分配的queue、stack内存空间进行复用,避免频繁申请和释放。

简单总结

实现成本 性能损耗 堆栈价值
FPS 简单 屏幕刷新会频繁唤醒 runloop
Ping 简单 会不停的唤醒主线程runloop
Runloop 中等
TimeProfiler 较复杂 插桩代码调用频繁

猜你喜欢

转载自juejin.im/post/7063364439226974222