卡顿优化

发现卡顿点

1. 使用instruments分析工具:

可以找到耗时多的代码


instruments

2. 使用代码,添加FPS监控

  • 通过 CADisplayLink 获取屏幕FPS
  • 开子线程,定时监测页面FPS
  • FPS过低时,通过 CrashReporter 记录堆栈信息
  • 添加脚本,每次编译,获取dSYM文件,保存
  • 卡顿异常时,上报堆栈信息文件
  • 使用 symbolicatecrash 反堆栈解析,发现造成卡顿的代码
获取页面FPS
- (id)init {
    self = [super init];
    if( self ){
        _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTick)];
        _displayLink.frameInterval = 2;
        [_displayLink setPaused:YES];
        // TODO 测试tracking状态下能否正常运行
        [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    }
    return self;
}

- (void)displayLinkTick {
    _lastTickTimestamp = GYM_CURRENT_MS;
    if (_lastUpdateTimestamp <= 0) {
        _lastUpdateTimestamp = _displayLink.timestamp;
        return;
    }
    _historyCount += _displayLink.frameInterval;
    CFTimeInterval interval = _displayLink.timestamp - _lastUpdateTimestamp;
    if(interval >= 1) {
        _lastUpdateTimestamp = _displayLink.timestamp;
        _currentFPS = _historyCount / interval;
        _historyCount = 0;
        [self fpsUpdated:_currentFPS];
    }
}

3. 不止与FPS,还有CPU&内存使用情况

获取CPU使用情况
float cpu_usage() {
  kern_return_t kr;
  task_info_data_t tinfo;
  mach_msg_type_number_t task_info_count;
  
  task_info_count = TASK_INFO_MAX;
  kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count);
  if (kr != KERN_SUCCESS) {
    return -1;
  }
  
  task_basic_info_t      basic_info;
  thread_array_t         thread_list;
  mach_msg_type_number_t thread_count;
  
  thread_info_data_t     thinfo;
  mach_msg_type_number_t thread_info_count;
  
  thread_basic_info_t basic_info_th;
  uint32_t stat_thread = 0; // Mach threads
  
  basic_info = (task_basic_info_t)tinfo;
  
  // get threads in the task
  kr = task_threads(mach_task_self(), &thread_list, &thread_count);
  if (kr != KERN_SUCCESS) {
    return -1;
  }
  if (thread_count > 0)
    stat_thread += thread_count;
  
  long tot_sec = 0;
  long tot_usec = 0;
  float tot_cpu = 0;
  int j;
  
  for (j = 0; j < (int)thread_count; j++)
  {
    thread_info_count = THREAD_INFO_MAX;
    kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
                     (thread_info_t)thinfo, &thread_info_count);
    if (kr != KERN_SUCCESS) {
      return -1;
    }
    
    basic_info_th = (thread_basic_info_t)thinfo;
    
    if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
      tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
      tot_usec = tot_usec + basic_info_th->user_time.microseconds + basic_info_th->system_time.microseconds;
      tot_cpu += basic_info_th->cpu_usage / (float)TH_USAGE_SCALE * 100.0;
    }
    
  } // for each thread
  
  kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t));
  assert(kr == KERN_SUCCESS);
  
  return tot_cpu;
}
获取内存使用情况
+ (CGFloat)memoryUsage {
  struct mach_task_basic_info taskBasicInfo;
  mach_msg_type_number_t taskInfoCount = sizeof(taskBasicInfo) / sizeof(integer_t);
  if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&taskBasicInfo, &taskInfoCount) == KERN_SUCCESS) {
    return taskBasicInfo.resident_size / (1024 * 1024);
  }
  return 0;
}

引文

github-GYMonitor

你可能感兴趣的:(卡顿优化)