思路
Ping主线程的核心思想是向主线程发送一个信号,一定时间内收到了主线程的回复,即表示当前主线程流畅运行。没有收到主线程的回复,即表示当前主线程在做耗时运算,发生了卡顿。
具体实现
目前昆虫线上使用的就是这套方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| self.semaphore = dispatch_semaphore_create(0); - (void)main { //判断是否需要上报 __weak typeof(self) weakSelf = self; void (^ verifyReport)(void) = ^() { __strong typeof(weakSelf) strongSelf = weakSelf; if (strongSelf.reportInfo.length > 0) { if (strongSelf.handler) { double responseTimeValue = floor([[NSDate date] timeIntervalSince1970] * 1000); double duration = responseTimeValue - strongSelf.startTimeValue; if (DEBUG) { NSLog(@"卡了%f,堆栈为--%@", duration, strongSelf.reportInfo); } strongSelf.handler(@{@"title": [InsectUtil dateFormatNow].length > 0 ? [InsectUtil dateFormatNow] : @"", @"duration": [NSString stringWithFormat:@"%.2f",duration],@"content": strongSelf.reportInfo }); } strongSelf.reportInfo = @""; } }; while (!self.cancelled) { if (_isApplicationInActive) { self.mainThreadBlock = YES; self.reportInfo = @""; self.startTimeValue = floor([[NSDate date] timeIntervalSince1970] * 1000); dispatch_async(dispatch_get_main_queue(), ^{ self.mainThreadBlock = NO; dispatch_semaphore_signal(self.semaphore); }); [NSThread sleepForTimeInterval:(self.threshold/1000)]; if (self.isMainThreadBlock) { self.reportInfo = [InsectBacktraceLogger insect_backtraceOfMainThread]; } dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER); // 卡顿超时情况; verifyReport(); } else { [NSThread sleepForTimeInterval:(self.threshold/1000)]; } }}
|