IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> BlockCanary介绍 -> 正文阅读

[移动开发]BlockCanary介绍

在这里插入图片描述

BlockCanary是什么

BlockCanary是一个Android平台的一个非侵入式的性能监控组件,应用只需要实现一个抽象类,提供一些该组件需要的上下文环境,就可以在平时使用应用的时候检测主线程上的各种卡慢问题,并通过组件提供的各种信息分析出原因并进行修复。

取名为BlockCanary则是为了向LeakCanary致敬,顺便本库的UI部分是从LeakCanary改来的。

BlockCanary设计原理

BlockCanary工作流程图
上图是BlockCanary的工作流程图,整个流程分为三个部分,分别是监控卡顿、捕获现场、保存现场记录到本地。三个部分分别执行在不同的线程、这也是上述图中三个区域颜色不同的原因,下面详细解释下起工作流程。

第一部分-接收消息

BlockCanary对象构造时,会使用HandlerThread开启两个线程、分别对应图中绿色和紫色两块区域,start方法开启后,会将自定义的Printer设置给主线程的Looper,这样自定义的Printer就能获取每一个message处理时打印的日志,如果不了解Handler机制,👉这里

//堆栈和cpu信息捕获线程
private static HandlerThreadWrapper sLoopThread = new HandlerThreadWrapper("loop");
//卡顿日志写线程
private static HandlerThreadWrapper sWriteLogThread = new HandlerThreadWrapper("writer");

第二部分-监控卡顿

当主线程Looper开始工作后,会从消息队列中获取待处理的message,接着会调用logging的println方法,而BlockCanary自定义的Printer就从println开始记录。

public static void loop() {
        //.....
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                return;
            }
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            //...handleMsg
            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
        }
    }
public void println(String x) {
        if (!mPrintingStarted) {
            mStartTimestamp = System.currentTimeMillis();
            mStartThreadTimestamp = SystemClock.currentThreadTimeMillis();
            mPrintingStarted = true;
            startDump();
        } else {
            final long endTime = System.currentTimeMillis();
            mPrintingStarted = false;
            if (isBlock(endTime)) {
                notifyBlockEvent(endTime);
            }
            stopDump();
        }
    }
    
    private boolean isBlock(long endTime) {
        return endTime - mStartTimestamp > mBlockThresholdMillis;
    }

首先记录当前消息处理前的时间,标记为mStartTimestamp(对应图中T1),然后通知捕获线程,该线程第一次延时thresold * 0.8,然后开始循环取dump调用栈和cpu信息。此时主线程不受影响,继续处理消息。

第三部分-记录卡顿

消息处理完后,会再次调用logging的println方法,此时记下结束时间(对应图中T2), 然后用T2-T1>mBlockThresholdMillis来判断是否为卡顿,若卡顿,则开始通知日志线程去写入现场日志到本地

private void notifyBlockEvent(final long endTime) {
        HandlerThreadFactory.getWriteLogThreadHandler().post(new Runnable() {
            @Override
            public void run() {
                mBlockListener.onBlockEvent(startTime, endTime, startThreadTime, endThreadTime);
            }
        });
    }

BlockCanary讨论

第一次看了BlockCanary的源码的时候,有一些疑惑,后面也想了想,记录在这里。

  1. 为什么需要延时threshold * 0.8才开始取dump线程堆栈和cpu信息?
    因为threshold是我们设定的卡顿时长阈值,这里*0.8可能主要是考虑性能影响,在如果本次方法执行时长小于threshold * 0.8,就不用去dump 堆栈和cpu信息,这样可以减少监控组件本身对cpu的消耗。
  2. BlockCanary能监控所有卡顿吗?
    目前从源代码来看,答案是不能,基于Handler的Message机制可以监控主线程消息的卡顿,但是项目中使用了IdleHandler的情况就监控不到。
  3. BlockCanary能准确捕捉到卡顿调用栈吗?
    不能,比如一个message里有两个方法,第一个方法耗时80ms,第二个耗时30毫秒,卡顿阈值100ms,此时这个message一共耗费了110毫秒,检测到卡顿,但是堆栈捕获到第二个方法调用栈,其实第一个调用栈才是最耗时的。
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-16 18:57:11  更:2021-11-16 18:57:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:49:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码