感觉这是一个很有意思的工具,可以检测UI线程处理每个message时间。如果时间长了,那么就发个通知,通知开发者哪里可能存在问题。原理并不难,不过作者能想出来这种方法来检测手机app的一些性能问题,还是挺有心的,应该给作者点个赞。
开源库的地址是 戳这里
哪些卡顿检查不出来
首先说下这个工具只能检测一些性能问题。卡顿的问题不只是因为message的执行时间过长。比如:界面的渲染是在Render Thread线程。主线程会把view#draw()方法的指令解析成GPU能读懂的指令,然后传给Render Thread线程。 GPU再根据这些指令进行渲染。绘制是一个很复杂的过程。虽然有了Render Thread线程来做渲染工作,大部分时间Render Thread 和主线程是并发进行的,但是还是会有一个点 两个线程是互相依赖的。他们需要相互等待来交换数据,以便将数据写入到 back buffer中。back buffer是从SurfaceFlinger 服务的buffer队列请求来的。当把渲染的数据写到back buffer后,会返回给SurfaceFlinger 服务的buffer队列。SurfaceFlinger会根据硬件屏幕刷新时钟Async来把buffer(这里叫frame buffer)给到android系统中进行屏幕展示。这里的要展示的frame buffer来自于back buffer。所以如果绘制不及时(>16ms), back buffer在16ms内没有装载完毕。那么SurfaceFlinger只能把之前的back buffer当成frame buffer提交给屏幕进程呈现。因此卡顿就产生了。
因此,绘制不及时有很多种。比如上面说的Render Thread线程绘制了一个很复杂的view(比如给view添加蒙层,就会导致绘制的复杂),因为主线程与Render Thread线程存在依赖,那么主线程需要等待,导致back buffer不能完成,进而产生卡顿。这时候UI线程中处理msg的时间并不长,只是一直在block等待。这种卡顿AndroidPerformanceMonitor并不能处理。
原理分析
原理就不贴代码了,几句话就能说完。贴代码反而影响问题的阐述。
我们知道,主线程的Looper工作在一个for循环中,每次从队列中拿到一个meesage进行处理。在处理每一个message时,在开始处理,到处理完成都会使用Printer来打印一些东西。开始时打印:
'' logging.println(">>>>> Dispatching to " + msg.target + " " +
'' msg.callback + ": " + msg.what);
结束时打印:
'' logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
这个Printer是Looper的mLogging成员变量,我们可以设置。原理就在这里。我们可以设置一个自定义的Printer。重写Printer的println(String)方法。在重写的println(String)方法中判断,如果参数string中包含“Dispatching to”,那么就往HandleThread线程的队列中添加一个延时300ms的runnable,runnable中处理卡顿信息的逻辑。如果判断参数string中包含“Finished“,那么如果HandleThread线程的队列 中的runnable还在,就清除这个runnable。即,说明这个message执行完还不到300ms,那么就认为处理这个message没有发生卡顿。当然如果打印”Finished“时,与”Dispatching“的时间差已经大于了300ms,那么runnable便已经执行了处理卡顿信息的逻辑。
大致原理就是这样。
网友评论