Dokit 卡顿检测原理

原理十分简略,主要还是利用 Printer 这个接口

Dokit 卡顿检测的 一个bug

判别 两次println 的履行间隔时刻 ,来判别是否产生了卡顿

这个检测的方案很简略, 可是光检测没用呀,还必需要检测出哪里卡了,所以必需要 获取主线程仓库

获取主线程仓库 必需要留意2点:

  1. 获取仓库的操作 一定要放到子线程去做, 主线程操作仓库 简单卡
  2. 即便放到子线程去操作,也要留意操控收集频率

对于dokit来说 Printer的完成类是 MonitorCore

收集仓库的完成类是 StackSampler

先看MonitorCore

Dokit 卡顿检测的 一个bug

这儿其实十分简略,便是判别一下 两次println的时刻间隔,发现卡顿

然后去sampler里边取仓库

看下StackSampler 是怎么 获取在子线程获取主线程仓库的?

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

Dokit 卡顿检测的 一个bug

咱们每次都是往这个子线程中去push一个音讯,然后履行咱们的runnable

Dokit 卡顿检测的 一个bug

这个里边其实便是有dumpinfo的办法了

Dokit 卡顿检测的 一个bug

这儿要留意 仓库是存储在一个map里边的,key是 获取仓库的时刻,value便是仓库的字符

全体上逻辑便是这样

Dokit的 缺陷

再看下 MonitorCore

Dokit 卡顿检测的 一个bug

这儿会产生一个状况,每次有音讯到来时,会发动start 然后再发动stop ,为啥?

由于你要确保大部分状况下,没有卡顿时 就不要收集仓库,

Dokit 卡顿检测的 一个bug

Dokit 卡顿检测的 一个bug

所以大部分状况下 收集仓库的 runnable 是没有机会履行的。

bug 就出现在这儿

仓库收集的默许推迟 是300ms

Dokit 卡顿检测的 一个bug

而咱们的卡顿阈值是200ms

Dokit 卡顿检测的 一个bug

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

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

可是你获取仓库 会发现获取不到的。为什么?

由于此刻 dump地点的runnable 还没开始履行呢,他要300ms以后才履行, 250ms你音讯过来了,直接触发了 stopDump

所以我们在运用dokit的时分 还是尽量修改一下这2个默许值

至少要确保 block的值 一定要大于 仓库收集的推迟阈值, 否则就会出现上述bug

别的收集仓库这个操作 假如要放到线上,引荐还是把优先级调到最低,这样对事务影响最小

Dokit 卡顿检测的 一个bug