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毫秒,检测到卡顿,但是堆栈捕获到第二个方法调用栈,其实第一个调用栈才是最耗时的。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BlockCanary是一个用于Android应用性能监控和问题排查的开源库。它可以帮助开发人员监测应用的主线程中的卡顿、ANR(应用未响应)和内存泄漏等问题,并提供详细的监测数据和堆栈跟踪,以便开发人员快速定位问题。 BlockCanary的工作原理是通过在应用主线程中插入监测代码来记录主线程的耗时操作,并根据设定的阈值来判断是否发生卡顿。一旦发现卡顿BlockCanary会收集相关的监测数据,包括耗时操作的具体信息和开始、结束时间等,并以通知的方式提醒开发人员。 BlockCanary的使用非常简单,只需要在Application的onCreate()方法中初始化BlockCanary即可。初始化时,可以设置卡顿阈值等参数,并可以选择是否将监测结果保存到文件中以供后续查看。在出现卡顿时,开发人员可以通过查看监测结果中的耗时操作和堆栈跟踪来定位问题的具体位置,并进行分析和排查。 BlockCanary的主要优点是简单易用,不需要侵入业务代码即可监测应用的性能问题。它提供了详细的监测数据和可视化的监测结果,能够帮助开发人员快速定位和解决问题。同时,BlockCanary还支持与其他性能监控工具和分析工具的集成,使其功能更加强大和灵活。 总之,BlockCanary是一个非常实用的Android应用性能监测工具,能够帮助开发人员及时发现和解决应用中的性能问题,提升用户体验。它的简单易用和丰富的功能使其成为开发人员调试和优化应用的重要利器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值