美文网首页
为 Fabric MOD 一个卡顿检测功能

为 Fabric MOD 一个卡顿检测功能

作者: hite和落雁 | 来源:发表于2018-10-29 17:30 被阅读126次

卡顿检测系统,用于检测 App 的主线程运行情况。在追求 N 个9奔溃之外,卡顿也是我们极其重要运行指标。
很遗憾,世界上最好的免费 APM 平台 Fabric 缺没有。而国内的 bugly、网易云捕等,都提供了类似的功能。如云捕的卡顿功能;

卡顿功能

说起来卡顿检测,技术原理很简单, 下面是来自 bugly 的 QA 里的描述

iOS 卡顿检查的依据是监控主线程 Runloop 的执行,观察执行耗时是否超过预定阀值(默认阀值为3000ms) 在监控到卡顿时会立即记录线程堆栈到本地,在App从后台切换到前台时,执行上报。

卡顿检测系统,这个大任务,可以分解为两部分:卡顿的检测 + 卡顿的展示和管理。

第一步,卡顿的收集

卡顿的收集,有现成的代码,核心代码可查看, gist

检测到之后,需要获取当前时刻的堆栈,所有线程的堆栈(其实只需要主线程就够了)。
OK,拿来主义,一个很有名 PLCrashReporter。我自己集成测试,在我的老古董机器,iPhone 6跑,卡顿是能检测到,但是整个软件基本不可用,整个界面全卡住了。PLCrashReporter 生成日志,

NSData *data = [crashReporter generateLiveReport];

性能非常差,完全不可用。

拿不到堆栈信息,无法展示,所以只能采用造轮子的方式。根据戴铭 blog 里的例子,我改造了下,如 gist 所示。我们收集到了所有堆栈的栈顶地址;接下来我们需要将这些栈信息符号化。
很容易想到的方案是传到自己的服务器上,用 Mac 环境处理堆栈的符号化,转换为可读的堆栈数据——代价太大,而且还不经济。

在浏览了 fabric 的各项 API 后,我发现有一个很讨好的接口,recordCustomExceptionName

2. 符号化堆栈,卡顿管理

fabric 提供了 recordCustomExceptionName接口,接口签名是

/**
 *  This method can be used to record a single exception structure in a report. This is particularly useful
 *  when your code interacts with non-native languages like Lua, C#, or Javascript. This call can be
 *  expensive and should only be used shortly before process termination. This API is not intended be to used
 *  to log NSException objects. All safely-reportable NSExceptions are automatically captured by
 *  Crashlytics.
 *
 *  @param name       The name of the custom exception
 *  @param reason     The reason this exception occurred
 *  @param frameArray An array of CLSStackFrame objects
 */
- (void)recordCustomExceptionName:(NSString *)name reason:(nullable NSString *)reason frameArray:(CLS_GENERIC_NSARRAY(CLSStackFrame *) *)frameArray;

我们利用这个接口,将第一步收集的堆栈数据传给 fabric,让 fabric 给我们符号化,而且 fabric 卡顿日志还能够聚合、分类、分组、跟踪。crash 日志的那一套都可以用上, fabric 用户对此是熟悉的。核心代码如下

// 将存储在 buffer 里的所有地址,生成对应的 stackFrame,用于给 crashlytics 来生成日志。
    NSMutableArray *callFrames = [NSMutableArray arrayWithCapacity:10];
    for(int k = 0; k < buffer.count; k++){
        NSUInteger addr = [[buffer objectAtIndex:k] unsignedLongValue];
        CLSStackFrame *sf = [CLSStackFrame stackFrameWithAddress:addr];
        [callFrames addObject:sf];
    }
    NSString *reason = [NSString stringWithFormat:@"卡顿的超时标准是,%ld",(long)limit];
    [[Crashlytics sharedInstance] recordCustomExceptionName:@"主线程卡顿的统计" reason:reason frameArray:callFrames];

至此,我们用很少的代价就做好了一个卡顿检测的系统,并且和奔溃功能一起使用,集中处理 APM 各项指标。

这个方案在月活几十万的 App 应用了快半年了。用户一点都没有感受到有卡顿系统,对现有系统影响很小。


卡顿检测 dashboard

所有的数据都在 crashlytics 里,选择 non-fatal,即可,从统计下来的数据来看,卡顿主要体验在;

  1. 读写文件
  2. 读写数据库
  3. 处理图片
  4. 动画渲染
  5. 在非主线程读一些主线程才能用的属性(奇怪吧?)

基本上和我们猜想是一致的,接下来就需要跟踪和处理这些卡顿。
目前这个系统有两个缺陷;

  1. 检查卡顿本身的 runloop 也被认为是卡顿
  2. 因为 recordCustomExceptionName 接口的限制,所有线程的栈都被合并到一个栈,但不影响核心卡顿代码的阅读。

相关文章

  • 为 Fabric MOD 一个卡顿检测功能

    卡顿检测系统,用于检测 App 的主线程运行情况。在追求 N 个9奔溃之外,卡顿也是我们极其重要运行指标。很遗憾,...

  • 卡顿检测资料

    微信iOS卡顿监控系统 卡顿方案思考 卡顿检测 移动端监控体系之技术原理 iOS性能检测

  • 卡顿优化

    卡顿优化 - CPU 卡顿优化 - GPU 离屏渲染 卡顿检测 耗电优化

  • ANR分析与实战

    卡顿单点问题检测方案

  • Android性能优化-App卡顿

    目录 1.卡顿简介 2.检测Jank:介绍监测卡顿的方法 3.修复卡顿问题:介绍如何修复卡顿问题; 4.卡顿通常的...

  • iOS通过runloop监控卡顿

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

  • iOS RunLoop

    如何检测或者优化app的卡顿?用instrument里面的time profiler自己做一个检测卡顿的小工具?(...

  • 无标题文章

    APP性能优化 UI卡顿优化 View的绘制原理 UI卡顿原理分析 UI卡顿检测分析 BlockCanary原理分...

  • iOS卡顿检测

    什么是卡顿? App 在使用过程中出现了一段时间的阻塞,其表现为在用户触摸屏幕后,需要等待一段时间 App 才有响...

  • iOS-卡顿简单监测三(NSTimer 实现+附实例)

    序言 之前写了两篇文章介绍如何检测卡顿 iOS实时卡顿检测-RunLoop(附实例)这是借助于信号量Semapho...

网友评论

      本文标题:为 Fabric MOD 一个卡顿检测功能

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