基于Method Trace工具解决UI卡顿的问题

        很久以前就看过使用Android studio的Method Trace工具调查函数性能或者效率的问题,一直没有在解决日常问题过程中实战过。最近刚好遇到了一个关闭wifi开关时wifi设置页面卡顿的问题,所以就想着尝试一下。虽然解决UI卡顿一般都用systrace工具,但是method trace可以查看各个线程中某个函数执行情况,理论上也是可以用来定位UI卡顿问题的。

首先启动method trace功能,然后关闭wifi,待卡顿过后,停止trace。Android studio会自动打开抓取的内容。 

虽然Eclipse通过ddms抓取的traceview也是可以查看函数调用情况,但是Adroid studio的method trace功能更强大,尤其是可以分线程查看,这就更方便我们查找问题了。由于UI卡顿肯定是主线程被block了,必然我们要看这段时间内主线程的执行情况。选中上图中的主线程,可以看到中间有个很长的长条,鼠标放上去之后,发现该函数执行了约1.5s(注意起始时间,与后面做对比时可以很方便确认多线程调用时函数执行先后顺序),那么可以确认,就是这个函数出的问题了。

定位到源码中的copyAndNotifyListeners函数,去掉其他逻辑后主逻辑如下

private void copyAndNotifyListeners(boolean notifyListeners) {

……1……

     synchronized (mLock) {

        ……2……

    }

……3……

}

直观的怀疑是执行完1处的逻辑之后,主线程要去拿锁,此时由于锁被其他线程占用,所以主线程要一直等待。但是这只是我们的怀疑,要找到证据才行。这又要体现出Method Trace工具的强大之处。图中的每个小方格都代表了函数的执行情况,包括函数名、函数执行时间以及各个函数之间的调用情况。原理上,如果逻辑2中有函数调用的话,必定能在图中体现出来。把图中卡顿地方前后位置放大之后,发现卡顿之前确实在调用1处的函数,而在卡顿之后恰好在调用2处的逻辑。这样,就为我们之前的假设找到了证据。

既然主线程要取的锁被占用,肯定是被其他线程占用着,具体是什么线程,可以通过图中左上角查看每个线程的调用情况来确认。果然,在某个线程中我们发现了与主线程类似的长条。查看函数调用堆栈的情况,确实在该函数中持有对应的锁,且该锁刚好是在主线程之前拿到的。这样卡顿的原因就找到了。进一步分析,该部分卡顿是由于子线程在持锁期间调用了WifiManager的接口,而这个接口在向WifiManager取数据时采用的是同步调用,而WifiManager最终是向WifiStateMachine中取数据,WifiStateMachine线程此时正在忙碌调用driver中的接口,无法及时处理这个请求,因此这就是应用层被卡住的原因。

虽然经过上面的分析,问题是WifiStateMachine引起的,但是一款优秀的应用,还是要首先检查自己能否兼容这种场景,自己的逻辑是否也存在问题。深入分析之后发现,子线程确实存在持锁范围过大的问题,可以进行优化,避免不必要的等待。

补充问题

在解决上面问题时,对android源码的@GuardedBy标记有些疑惑,这个标记有啥作用呢?我直观的以为这个可以当成一把锁来用,但这只是我的假设而已,肯定要验证一下才能踏实。查阅了一些资料,感觉还是云里雾里,所以还是自己做实验看看把。

写了上面的测试代码,编译之后得到.class文件,通过javap -c Test.class后查看编译后的代码

从这个结果可以看出,@GuardedBy标签并没有对编译后的结果产生影响,也就没有同步作用。事实上该标签和@Override标签的功能是一致的,更多的作用是一种标记,标记这个变量或者这个函数是需要同步的,同时编译器在编译时可以根据这些标签做lint检查之类的工作。在日常工作中,可以合理的使用这些标签以增强代码逻辑的可读性,同时也方便其他同学阅读此处逻辑时能更快的领会设计意图。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 30,023评论 8 265
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,169评论 19 139
  • 1、2014年8月14号,研究生舍友陈给我打电话,说无聊就给我打个电话。我对她表达了有了爱情之后就忘了我的牢骚,说...
    janet阅读 1,648评论 0 1
  • 先来个图吧 大概的效果就是这样,代码就一个监听事件,把需要移动的View添加这个监听事件就可以了,具体的参数要根据...
    隔壁老王的杂货铺阅读 3,816评论 0 0
  • 典韦,东汉末年曹操部将,相貌魁梧,力大过人,一对铁戟,好不霸气。本属张邈,后归曹操。曹操征讨吕布时被募为陷阵,表现...
    老爷子l阅读 4,204评论 0 0

友情链接更多精彩内容