前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)

Android卡顿优化 | ANR分析与实战(附ANR-WatchDog源码分析及实战、与AndroidPerformanceMonitor的区别)

作者头像
凌川江雪
发布2020-04-09 15:34:43
5.1K2
发布2020-04-09 15:34:43
举报
文章被收录于专栏:李蔚蓬的专栏

本文要点

  • ANR概述
  • 发生ANR后Android系统的执行流程
  • ANR-WatchDog原理与实战
  • ANR的传统解决套路
  • ANR模拟实战
  • 线上ANR监控方案【ANR-WatchDog原理分析】
  • ANR-WatchDog实战
  • ANR-WatchDog总结
  • ANR-WatchDog与AndroidPerformanceMonitor的区别

项目GitHub

ANR概述

  • KeyDispatchTimeout,5s 即按键或者触摸事件,在特定的时间(一般5s)之内没有响应;
  • BroadcastTimeout,前台10s,后台60s BroadReceiver 在特定的时间(一般前台10s,后台60s)之内没有响应完成;
  • ServiceTimeout,前台20s,后台200s Service 在特定的时间(一般前台20s,后台200s)之内没有处理完成;

发生ANR后Android系统的执行流程

  • APP发生ANR
  • 进程接收异常终止信号,开始写入进程ANR信息(当时场景,包含当前线程所有堆栈信息、CPU/IO的使用情况等);
  • 弹出ANR提示框,提示用户关闭APP或者继续等待;(不同ROM表现不同,有的手机厂商会去掉这个提示框)

ANR的传统解决套路

  • 【线下】在AS的Terminal中,使用 adb pull data/anr/traces.txt 要存储在本地的路径 导出上面提到的ANR现场信息文件; 导出来后,便可对文件内容进行详细分析:从CPU、IO、锁冲突等原因思考;

ANR模拟实战

  • 模拟ANR原因:锁冲突; 更改代码:

运行程序,等到程序ANR或崩溃, 在Terminal使用刚刚提到的命令,导出ANR的信息文件:

生成文件:

打开文件,可以找到原因:

上次的BlockCanary同样捕捉到原因:

线下套路其实就是在APP发生ANR时, 导出信息文件, 查看文件,结合代码进行分析;

线上ANR监控方案

  • 通过FileOberver监控上述的ANR信息文件的变化, 如果这个文件发生了变化,那就说明发生了ANR, 那便可以把它上报到服务器,进行详细的分析; 【高版本需注意权限问题】
  • ANR-WatchDog

    ANRWatchDog中,用一个绑定了主线程Looper的Handler, 去处理_ticker【一个Runnable任务单元】; 任务单元对一些值进行了处理,如_tick_reported

    _tick在初始为ANRWatchDog的全局变量时,被赋值为0;^^^^^^^^^^^^^^^^^ ANRWatchDogrun()中, 首先被利用去判定_ticker被post没有(因为一开始就_tick为0的话说明_tick还没被post), 没有便将_tick=加上卡顿周期,之后post了_ticker 此时_tick不为0!!^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ticker中的run(),再一次将_tick置零;^^^^^^^^^^^^^^^^^^^^^^^^^^ 所以只要_ticker不被处理,其run()便不会执行, _tick就不会被置零,

    由此根据_tick的值可以判断_ticker是否被处理了; _tick重新归零则主线程处理了_ticker _tick不为零则判定主线程卡顿,它没处理_tick!!!!!!!!

    ANRWatchDogrun()中, 用刚说的主线程Handler,post了_ticker这个任务, 然后自己sleep一段时间【即一个卡顿周期,稍后细说】, 如果sleep结束之后,如果_tick != 0 && !_reported 则说明主线程还没有处理_tickerrun() 没有处理_ticker这个任务单元, 那便认为主线程发生了卡顿【如源码注释所示】:!!!!!! 确定发生了卡顿,就开始封装一个ANRError,进行后续处理了:

    另外补充一下, ANRWatchDog提供了两个重载的构造器, 提供给开发者对卡顿判定周期进行设置,开发者不设置则使用默认配置 【跟BlockCanary同一个德行】

    接着仔细看ANRError的构造流程

    这里是有两种构造方式New()NewMainOnly(),其最终处理都差不多, 就是通过mainLooper拿到主线程, 再通过主线程拿到现场的堆栈信息 最后返回构造好的ANRError实例:

    拿到ANRError实例之后, 通过_anrListener.onAppNotResponding(error);回调机制处理ANRError实例;

    回调机制就妙啊!^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 刚刚的_anrListener.onAppNotResponding(error);只是一个应用层上的调用; onAppNotResponding()的实现方式暴露给开发者了, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 在外部可以通过setANRListener()自己定制包含不同处理方式的ANRListener ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    开发者不定制,则使用框架自带的默认处理方式呗: 处理方式简单粗暴哈,直接把ANRError丢出去, 这样APP就直接崩溃了:

    ANRError乃是Error的子类:

ANR-WatchDog实战

  • 引入依赖
  • 初始化ANR-WatchDog:
  • 还是上面那个项目,手动阻塞60s, 运行程序, 程序会5s后崩溃【5s是默认周期时间,崩溃操作见上面源码分析】 logcat定位关键字fatal,可以看到ANRError打印的信息, 信息中包括了崩溃现场所有线程堆栈信息 以及显示bug代码的位置

优化: 当然默认的APP崩溃处理法并不妥当, 影响用户体验, 实际开发中, 我们可以自己定义ANRListener,自定义处理方式【上面说过了】, 把堆栈信息上报给服务器就是了!!!!

总结

  • 非浸入式
  • 弥补高版本无权限问题

与AndroidPerformanceMonitor的区别

  • AndroidPerformanceMonitor: 原理是基于Handler-Message机制, 监控主线程每一个Message的执行, 在每一个Message的分发执行前后,进行信息处理; (不足: 一般没有阻塞的情况下, 每一个Message的执行时间是非常短暂的, 达不到ANR的级别; 而且InputEvent在queue.next中block,不会继续执行dispatchMessage, 而是从native回调给InputEventReceiver.dispatchInputEvent处理分发, 所以BlockCanary也就无法监控到这类ANR)
  • ANR-WatchDog: 不管主线程是怎么执行的, 只管最后的结果, 我sleep一个周期之后,就要看我_tick值有没有被修改, 没被修改就是ANR!
  • AndroidPerformanceMonitor适合全程监控卡顿, ANR-WatchDog适合补充ANR监控; 两者可以相辅相成,结合使用!
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ANR概述
  • 发生ANR后Android系统的执行流程
  • ANR的传统解决套路
  • ANR模拟实战
  • 线上ANR监控方案
  • ANR-WatchDog实战
  • 总结
  • 与AndroidPerformanceMonitor的区别
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档