BlockCanary的监控流程分析

原理概述

Android系统中的消息机制是依靠Looper不断从MessageQueue中取出Message进行处理,卡顿的直接原因是处理Message的时间过长,所以监控卡顿主要是监控Message的处理时长。

BlockCanary通过重设Looper中的Printer对象来记录Message的处理时长,当时长超过阀值时即发生卡顿,获取此时的栈和CPU信息供排查原因。

使用

    //依赖
    debugImplementation 'com.github.markzhai:blockcanary-android:1.5.0'
    releaseImplementation 'com.github.markzhai:blockcanary-no-op:1.5.0'

    //初始化
    BlockCanary.install(this, new BlockCanaryContext()).start();

初始化

BlockCanary

BlockCanary的参数设置在BlockCanaryContext类中,通过继承可以修改配置

监控

初始化拿到BlockCanary单例后便开始监控

BlockCanary

向MainLooper中设置Printer

Looper
Looper.loop

Looper在消息处理的过程中会通过Printer打印日志,BlockCanary正是利用了这一点来测量处理Message所耗的时长

Printer对象的初始化在BlockCanaryInternals单例中

BlockCanaryInternals

Looper通过调用Printer的println来打印日志,BlockCanary的监控必须放在此方法内

LooperMonitor

当Message处理的时间超过阀值会回调onBlockEvent

栈、CPU信息

识别出了卡顿,接下来就是分析卡顿产生的原因

LooperMonitor

Message在每次处理时,都会记录栈、CPU信息

AbstractSampler

StackSampler继承自AbstractSampler,在AbstractSampler内部通过HandlerThread新启线程,利用Handler的postDelayed方法循环取样

StackSampler

取样信息存在LinkedHashMap中

CPU

CpuSampler

与StackSampler代码逻辑类似,只不过信息的来源不同了。CpuSampler的信息是通过读取系统log文件的形式获取的,通过解析获取想要的信息组成字符串,存入LinkedHashMap中

信息获取

BlockCanaryInternals

发生卡顿时,会回调onBlockEvent,四个参数分别表示:记录开始时间点、记录结束时间点、记录开始时间点线程所运行时间、记录结束时间点线程所运行时间

StackSampler

sStackMap中的key是记录的时间点,落在记录开始、结束时间点中间的栈信息都是同一Message处理所产生的

同理获取CPU信息,组装成BlockInfo对象,由LogWriter写入单独文件进行存储

信息展示

BlockCanaryInternals
BlockCanary

之前添加的监听被回调

跳转到信息展示页面DisplayActivity

DisplayActivity

在页面启动时加载卡顿信息

DisplayActivity.LoadBlocks

加载的过程是封装为LoadBlocks的Runnable

LoadBlocks

获取保存的所有日志文件

转成BlockInfoEx对象

将数据设置到Activity并更新UI

你可能感兴趣的:(BlockCanary的监控流程分析)