RunLoop监控app卡顿

作者: 我是繁星 | 来源:发表于2019-04-26 17:28 被阅读244次

本文意义在分析如何利用runloop监控卡顿。代码可以看戴铭大佬的代码

思路

首先思路就是利用CFRunloopObserverContext监控主线程runloop的状态,通过主线程中任务执行的时间来判断是否有卡顿存在。
CFRunloopObserverContext一共有6种状态

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    //即将进入runloop
    kCFRunLoopEntry = (1UL << 0),
    //即将处理timer
    kCFRunLoopBeforeTimers = (1UL << 1),
    //即将处理source
    kCFRunLoopBeforeSources = (1UL << 2),
    //即将进入休眠
    kCFRunLoopBeforeWaiting = (1UL << 5),
    //被唤醒但是还开始处理事件
    kCFRunLoopAfterWaiting = (1UL << 6),
    //runloop已经退出
    kCFRunLoopExit = (1UL << 7),
    kCFRunLoopAllActivities = 0x0FFFFFFFU
};

下图所示的是runloop的工作流程和对应的observer。


未命名文件-11.png

解释一下其工作过程,在进入runloop之后,当前runloop会不断按照在kCFRunLoopBeforeTimers-> kCFRunLoopBeforeSources-> kCFRunLoopBeforeWaiting-> kCFRunLoopAfterWaiting的顺序循环,直到接收到退出runloop的消息,那么我们只要知道线程任务在哪个状态区间执行的并且抓取这个时间间隔,如果时间间隔超过阈值,则说明卡顿,上报堆栈信息。

由上图可以看出真正处理事务的状态区间分别是:

  • KCFRunloopBeforeSources->KCFRunLoopBeforeWaiting
  • kCFRunLoopAfterWaiting-> kCFRunLoopBeforeTimers

代码如下:

#import "SMLagMonitor.h"
@interface SMLagMonitor(){
    int timeoutCount;
    CFRunLoopObserverRef runLoopObserver;
    @public
    dispatch_semaphore_t dispatchSemaphore;
    CFRunLoopActivity runloopActivity;
}
@property (nonatomic, strong) NSTimer * cpuMonitorTimer;
@end
@implementation SMLagMonitor
+ (instancetype)shareInstance{
    static id instance = nil;
    static dispatch_once_t dispatchOnce;
    dispatch_once(&dispatchOnce, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (void)beginMonitor{
    if (runLoopObserver){
        return;
    }
    dispatchSemaphore = dispatch_semaphore_create(0);
    CFRunLoopObserverContext context = {0,(__bridge void *)self,NULL,NULL};
    runLoopObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, &runloopObserverCallBack, &context);
    CFRunLoopAddObserver(CFRunLoopGetMain(), runLoopObserver, kCFRunLoopCommonModes);
    
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        while (YES) {
            //dispatch_semaphore_wait方法如果超时则会返回一个不等于0的整数,收到dispatch_semaphore_signal的时候会返回0
            long semaphoreWait = dispatch_semaphore_wait(self->dispatchSemaphore, dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC));
            if (semaphoreWait != 0){
                if (!self->runLoopObserver){
                    self->timeoutCount = 0;
                    self->dispatchSemaphore = 0;
                    self->runloopActivity = 0;
                    return ;
                }
                //BeforeSource和AfterWaiting这两个状态区间能够监测到是否卡顿
                if (self->runloopActivity == kCFRunLoopBeforeSources || self->runloopActivity == kCFRunLoopAfterWaiting){
                    NSLog(@"monitor trigger");
                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                        //上报堆栈
                    });
                }
            }
            self->timeoutCount = 0;
        }
    });
    
}

static void runloopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void * info){
    SMLagMonitor *lagMonitor = (__bridge SMLagMonitor *)info;
    lagMonitor->runloopActivity = activity;
    dispatch_semaphore_t semaphore = lagMonitor->dispatchSemaphore;
    dispatch_semaphore_signal(semaphore);
}

@end

相关文章

  • RunLoop监控app卡顿

    本文意义在分析如何利用runloop监控卡顿。代码可以看戴铭大佬的代码 思路 首先思路就是利用CFRunloopO...

  • iOS通过runloop监控卡顿

    质量监控-卡顿检测iOS实时卡顿监控基于Runloop简单监测iOS卡顿的demo微信iOS卡顿监控系统iOS-R...

  • 常规优化技巧

    卡顿优化 添加Observer到主线程RunLoop中,通过监听RunLoop状态切换的耗时,以达到监控卡顿的目的...

  • 如何利用 RunLoop 监控 app 卡顿

    本文意义在分析如何利用runloop监控卡顿。代码可以看戴铭大佬的代码 卡顿问题的几种原因 复杂 UI 、图文混排...

  • Runloop 之 监控app应用卡顿

    卡顿问题的原因: 复杂 UI 、图文混排的绘制量过大 在主线程上做网络同步请求 在主线程做大量的 IO 操作 运算...

  • 戴铭(iOS开发课)读书笔记:13章节-卡顿监控

    原文链接:如何利用 RunLoop 原理去监控卡顿? 前言 一个App想要提升用户体验最重要的就是 降低程序崩溃 ...

  • iOS常规的优化技巧

    原文地址 卡顿优化 添加Observer到主线程RunLoop中,通过监听RunLoop状态切换的耗时,以达到监控...

  • 监控卡顿-Runloop

    1 对主线程Runloop注册一个回调函数runLoopObserverCallBack。在每次runloop的C...

  • Runloop监控卡顿

    一、监控卡顿的原理 1.1、原理 我们通过监听 NSRunLoop 的状态,就能够发现调用方法是否执行 时间过长,...

  • iOS开发中的卡顿分析

    市面上的iOS卡顿分析方案有三种:监控FPS、监控RunLoop、ping主线程。 方案一:监控FPS 一般来说,...

网友评论

    本文标题:RunLoop监控app卡顿

    本文链接:https://www.haomeiwen.com/subject/adqqnqtx.html