Runloop卡顿监测

1,079 阅读1分钟

卡顿的原因

  • CPU相关
    1. 在主线程做大量的 IO 操作;
    2. 在主线程上做网络同步请求;
    3. 过多线程资源抢夺;
  • GPU相关
    1. 复杂 UI 、图文混排的绘制量过大;
    2. 大量的渲染算法

卡顿检测原理

  • 通过监控 RunLoop 的状态来判断是否会出现卡顿。 RunLoop 的目的是,当有事件要去处理时保持线程忙,当没有事件要处理时让线程进入休眠。 如果 RunLoop 的线程,进入睡眠前方法的执行时间过长而导致无法进入睡眠,或者线程唤醒后接收消息时间过长而无法进入下一步的话,就可以认为是线程受阻了。如果这个线程是主线程的话,表现出来的就是出现了卡顿。
Runloop的六个状态
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry , //进入loop
    kCFRunLoopBeforeTimers ,  //即将处理Timer
    kCFRunLoopBeforeSources , //即将处理Source
    kCFRunLoopBeforeWaiting , //即将进入睡眠
    kCFRunLoopAfterWaiting ), //刚从睡眠中唤醒
    kCFRunLoopExit , //退出loop
    kCFRunLoopAllActivities// loop所有状态改变
}

第一步

监听主线程runloop的状态变化
  // 创建observer
    CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL};
    _runLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, &runloopObserverCallBack, &context);
    // 添加observer
    CFRunLoopAddObserver(CFRunLoopGetMain(), _runLoopObserver, kCFRunLoopDefaultMode);
创建一个持续的子线程专门用来监控主线程的 RunLoop 状态。

image.png

image.png

image.png

image.png

image.png