本文要点
- 为何需要自动化检测方案
- 自动卡顿检测方案原理
- 看一下Looper.loop()源码
- 实现思路
- AndroidPerformanceMonitor实战
- 基于AndroidPerformanceMonitor源码简析
- 接下来我们讨论一下方案的不足
- 自动检测方案优化
项目GitHub
为何需要自动化检测方案
- 前面提到过的系统工具只适合线下针对性分析,无法带到线上!
- 线上及测试环节需要自动化检测方案
方案原理
- 源于Android的消息处理机制;
一个线程不管有多少Handler,只会有一个Looper存在,
主线程中所有的代码,都会通过Looper.loop()执行; - loop()中有一个
mLogging
对象,
它在每个Message
处理前后都会被调用: - 如果主线程发生卡顿,
一定是在dispatchMessage
执行了耗时操作!Handler机制图
由此,我们便可以通过
mLogging
对象
对dispatchMessage
执行的时间进行监控;
看一下Looper.loop()源码
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
// Allow overriding a threshold with a system prop. e.g.
// adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
final int thresholdOverride =
SystemProperties.getInt("log.looper."
+ Process.myUid() + "."
+ Thread.currentThread().getName()
+ ".slow", 0);
boolean slowDeliveryDetected = false;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
if (thresholdOverride > 0) {
slowDispatchThresholdMs = thresholdOverride;
slowDeliveryThresholdMs = thresho