iOS 性能监测
卡顿监测:通过侦听主线程runloop事件方式(配合信号量)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#import "LagMonitor.h" @interface LagMonitor() @property(nonatomic,strong) dispatch_semaphore_t semaphore; @property(nonatomic,assign) int timeoutCount; @property(nonatomic,assign) CFRunLoopActivity activity; @end @implementation LagMonitor{ CFRunLoopObserverRef observer; } +(instancetype)getInstance{ static dispatch_once_t onceToken; static LagMonitor * _lagMonitor; dispatch_once(&onceToken, ^{ _lagMonitor = [[LagMonitor alloc] init]; }); return _lagMonitor; }; -(void)startMonitor{ if (observer) { return; } _semaphore = dispatch_semaphore_create(0); _timeoutCount = 0; CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL}; observer = CFRunLoopObserverCreate(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, &lagMonitorRunLoopObserverCallBack, &context); CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes); [self initChildThread]; } -(void)stopMonitor{ if(observer){ CFRunLoopObserverInvalidate(observer); observer = NULL; } } static void lagMonitorRunLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info){ LagMonitor * _monitor = (__bridge LagMonitor *)(info); _monitor.activity = activity; dispatch_semaphore_signal(_monitor.semaphore); } -(void)initChildThread{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ while (YES) { long result = dispatch_semaphore_wait(self.semaphore, dispatch_time(DISPATCH_TIME_NOW, 50*NSEC_PER_MSEC)); if (result != 0) { if (self.activity==kCFRunLoopBeforeSources || self.activity==kCFRunLoopAfterWaiting) { if (++self.timeoutCount < 5) { continue; } NSLog(@"主线程卡顿了 ......."); dispatch_async(dispatch_get_global_queue(0, 0), ^{ //通过 PLCrashReporter 获取主线程的卡顿堆栈, 并进行记录或是择机上传 NSLog(@"记录卡顿 ......."); }); } } self.timeoutCount = 0; } }); } @end
卡顿监测:通过子线程ping主线程方式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #import "Lag2Monitor.h" 2 3 @interface Lag2Monitor() 4 @property(nonatomic,assign) BOOL isLag; 5 @property(nonatomic,assign) int timeCount; 6 @property(nonatomic,strong) NSTimer * timer; 7 @end 8 9 @implementation Lag2Monitor 10 11 +(instancetype)getInstance{ 12 static dispatch_once_t onceToken; 13 static Lag2Monitor * _lagMonitor; 14 dispatch_once(&onceToken, ^{ 15 _lagMonitor = [[Lag2Monitor alloc] init]; 16 }); 17 return _lagMonitor; 18 }; 19 20 -(void)startMonitor{ 21 if (_timer) { 22 return; 23 } 24 _isLag = NO; 25 _timeCount = 0; 26 27 dispatch_async(dispatch_get_global_queue(0, 0), ^{ 28 [[NSThread currentThread] setName:@"Monitor_sub_thread"]; 29 __weak Lag2Monitor * weakSelf = self; 30 self.timer = [NSTimer scheduledTimerWithTimeInterval:0.05 repeats:YES block:^(NSTimer * _Nonnull timer) { 31 if (!weakSelf.isLag) { 32 weakSelf.timeCount ++; 33 if (weakSelf.timeCount > 4) { 34 NSLog(@"主线程卡顿了 ......."); 35 weakSelf.timeCount = 0; 36 dispatch_async(dispatch_get_global_queue(0, 0), ^{ 37 //通过 PLCrashReporter 获取主线程的卡顿堆栈, 并进行记录或是择机上传 38 NSLog(@"记录卡顿 ......."); 39 }); 40 } 41 } 42 dispatch_async(dispatch_get_main_queue(), ^{ 43 weakSelf.isLag = YES; 44 weakSelf.timeCount = 0; 45 }); 46 }]; 47 [[NSRunLoop currentRunLoop] run]; 48 }); 49 } 50 51 -(void)stopMonitor{ 52 if(self.timer){ 53 [self.timer invalidate]; 54 self.timer = NULL; 55 } 56 } 57 58 @end
卡顿监测:通过CADisplayLink记录FPS
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #import "FPSMonitor.h" 2 #import <UIKit/UIKit.h> 3 @interface FPSMonitor () 4 5 @property(nonatomic,strong) CADisplayLink * displayLink; 6 @property(nonatomic,assign) NSUInteger fpsCount; 7 @property(nonatomic,assign) NSTimeInterval lastTimesmap; 8 9 @end 10 11 @implementation FPSMonitor 12 13 +(instancetype)getInstance{ 14 static dispatch_once_t onceToken; 15 static FPSMonitor * _fpsMonitor; 16 dispatch_once(&onceToken, ^{ 17 _fpsMonitor = [[FPSMonitor alloc] init]; 18 }); 19 return _fpsMonitor; 20 }; 21 22 -(void)startMonitor{ 23 if (_displayLink) { 24 return; 25 } 26 _fpsCount = 0; 27 _lastTimesmap = 0; 28 _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkSelector:)]; 29 [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 30 } 31 32 -(void)displayLinkSelector:(CADisplayLink *)sender{ 33 _fpsCount ++; 34 if (_lastTimesmap==0) { 35 _lastTimesmap = sender.timestamp; 36 return; 37 } 38 if (sender.timestamp - _lastTimesmap >= 1) { 39 int fps = _fpsCount/(sender.timestamp - _lastTimesmap); 40 NSLog(@"displayCount FPS:%d",fps); 41 if (fps < 30) { 42 dispatch_async(dispatch_get_global_queue(0, 0), ^{ 43 //通过 PLCrashReporter 获取主线程的卡顿堆栈, 并进行记录或是择机上传 44 NSLog(@"低于30FPS,记录卡顿 ......."); 45 }); 46 } 47 _fpsCount = 0; 48 _lastTimesmap = sender.timestamp; 49 } 50 } 51 52 -(void)stopMonitor{ 53 if(_displayLink){ 54 [_displayLink invalidate]; 55 _displayLink = NULL; 56 } 57 } 58 59 @end
给些链接:
http://wereadteam.github.io/2016/12/12/Monitor/#more
http://www.tanhao.me/code/151113.html/
https://yq.aliyun.com/articles/10729
https://yq.aliyun.com/articles/17729?spm=5176.100239.blogcont10729.8.tfuWol
解决问题的能力很关键~(iOS开发交流群:219926126)