iOS主线程卡顿监测

iOS开发过程中,我们有时需要监控主线程的卡顿情况,本文介绍主线程卡顿的实现方法。

新建MainThreadMonitor类,并且在.h中声明方法。

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MainThreadMonitor : NSObject

+ (instancetype)sharedInstance;

- (void)start;
- (void)stop;

@end

NS_ASSUME_NONNULL_END

sharedInstance为单例方法,返回MainThreadMonitor类的实例。start为开始检测,stop为结束检测。

#import "MainThreadMonitor.h"

@interface MainThreadMonitor ()

@property(nonatomic, strong) dispatch_semaphore_t semaphore;
@property(nonatomic, assign) BOOL isMonitoring;
@property(nonatomic, assign) NSTimeInterval interval;
@property(nonatomic, assign) BOOL timeout;

@end

@implementation MainThreadMonitor

+ (instancetype)sharedInstance
{
    
    
    static MainThreadMonitor *sharedInstance = nil;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
    
    
        sharedInstance = [[MainThreadMonitor alloc] init];
    });
    
    return sharedInstance;
}

- (void)start
{
    
    
    self.isMonitoring = YES;
    self.interval = 0.08;
    self.semaphore = dispatch_semaphore_create(0);
    
    __weak typeof (self) weakSelf = self;
  
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
    
      
        while (weakSelf.isMonitoring) {
    
    
            weakSelf.timeout = YES;
            dispatch_async(dispatch_get_main_queue(), ^{
    
    
                weakSelf.timeout = NO;
                dispatch_semaphore_signal(weakSelf.semaphore);
            });
            
            [NSThread sleepForTimeInterval:weakSelf.interval];
            
            if (weakSelf.timeout) {
    
    
                NSLog(@"Main thead is blocked");
            }
            dispatch_semaphore_wait(weakSelf.semaphore, DISPATCH_TIME_FOREVER);
        }
        
    });
}

- (void)stop
{
    
    
    self.isMonitoring = NO;
}

@end

sharedInstance使用dispatch_once_t构建了单例方法。

isMonitoring属性代表当前是否在检测主线程卡顿状态。

interval为卡顿时间,当前设置为0.08s。

semaphore为信号量,用于控制当前轮次的检测是否完成。

timeout为超时标记,如果timeout为YES,代表主线程出现了卡顿。

监控方法的实现主要原理为开辟了一个子线程,在子线程内设置一个循环,不停地监控卡顿状态。在每次循环内部,获取主线程的队列然后设置timeout为NO,子线程sleep时间设置为80ms,如果子线程sleep结束时主线程还没有设置timeout,代表当前出现了卡顿。代码内部加入了信号量semaphore,主要控制当前卡顿检测出来以后,再进行下一次检测,防止一次卡顿被多次检测。

猜你喜欢

转载自blog.csdn.net/u011608357/article/details/128517472