Dokit 卡顿检测的 一个bug

Dokit 卡顿检测原理

原理非常简单,主要还是利用 Printer 这个接口

判断 两次println 的执行间隔时间 ,来判断是否发生了卡顿

这个检测的方案很简单, 但是光检测没用呀,还必须要检测出哪里卡了,所以必须要 获取主线程的堆栈,

获取主线程堆栈 必须要注意2点:

  1. 获取堆栈的操作 一定要放到子线程去做, 主线程操作堆栈 容易卡
  2. 即使放到子线程去操作,也要注意控制采集频率

对于dokit来说 Printer的实现类是 MonitorCore

采集堆栈的实现类是 StackSampler

先看MonitorCore

这里其实非常简单,就是判断一下 两次println的时间间隔,发现卡顿

然后去sampler里面取堆栈

看下StackSampler 是如何 获取在子线程获取主线程堆栈的?

首先肯定是有一个子线程的

我们每次都是往这个子线程中去push一个消息,然后执行我们的runnable

这个里面其实就是有dumpinfo的方法了

这里要注意 堆栈是存储在一个map里面的,key是 获取堆栈的时间,value就是堆栈的字符串

整体上逻辑就是这样

Dokit的 缺陷

再看下 MonitorCore

这里会发生一个情况,每次有消息到来时,会启动start 然后再启动stop ,为啥?

因为你要保证大部分情况下,没有卡顿时 就不要采集堆栈,

所以大部分情况下 采集堆栈的 runnable 是没有机会执行的。

bug 就出现在这里

堆栈采集的默认延迟 是300ms

而我们的卡顿阈值是200ms

那这里就会有一个问题了, 假设一个卡顿是250ms

那么肯定会触发 卡顿的检测,isBlock方法 会返回true。

但是你获取堆栈 会发现获取不到的。为什么?

因为此时 dump所在的runnable 还没开始执行呢,他要300ms以后才执行, 250ms你消息过来了,直接触发了 stopDump

所以大家在使用dokit的时候 还是尽量修改一下这2个默认值

至少要保证 block的值 一定要大于 堆栈采集的延迟阈值, 否则就会出现上述bug

另外采集堆栈这个操作 如果要放到线上,推荐还是把优先级调到最低,这样对业务影响最小

相关推荐
hai_android3 小时前
Android 嵌套滑动冲突:内部拦截 vs 外部拦截实战
android·android studio·android jetpack
木子欢儿4 小时前
Zabbix 7.4 Alpine 版 Docker Compose 部署
android·运维·docker·容器·zabbix
素师良码5 小时前
第9篇:Android驱动踩坑实录:DSI RX FIFO前置脏0、数据错位复盘
android
夜雪一千6 小时前
如何在MySQL中实现字段级加密
android·数据库·mysql
夜雪一千6 小时前
MySQL 如何存储经纬度坐标:选型、建表、空间查询实战
android·mysql·adb
JMchen6 小时前
集成第三方 C/C++ 库到 Android NDK 项目:OpenCV 与 FFmpeg 实战指南
android·opencv·cmake
有毒的教程7 小时前
Dev-C++ 使用扩展库两种方式:DevPak一键安装 / 手动配置(重点)
android·c++·adb
mmsx8 小时前
Android 测绘数值基础:测量单位系统与七四参数、高程拟合
android
郑州光合科技余经理8 小时前
出海外卖平台:支付对接为什么要和下单收款分开
android·java·开发语言·前端·后端·php·ai编程
夜雪一千8 小时前
MySQL 如何提高查询速度:从索引、SQL、表结构到实战调优
android·sql·mysql