背景
我的App怎么这么卡,谁在代码里下毒了!
有一天突然发现debug包运行变的特别卡顿,经过下面的简单测试发现debug包在Android 14上出了问题。
二
问题排查纪录
常规手段排查
使用了systrace以及内部的debug包 trace工具dutrace进行排查。
结论:CPU空闲,主线程无明显阻塞,看上去就是纯方法执行耗时。
发现怀疑点
第一步排查过程中没有特别大的收获,但是我用dutrace工具排查时发现了一个异常现象。这里简单介绍一下dutrace的实现原理:
dutrace是利用inline hook在artmethod的执行前后加上atrace的点再通过perfetto ui工具展示。有以下优点:
1. 支持线下分析函数执行流程,函数耗时。
2. 在分析函数调用流程下:
a. 可以查看整个过程的函数调用(包括framework函数);
b. 能够指定监控的函数和线程有效过滤无用trace;
c. 动态配置不需要重新打包。
3. 可使用现成的UI分析工具,有系统关键线程的函数调用,例如渲染耗时、线程锁,GC 耗时等,还有 I/O 操作、CPU 负载等事件。
流程图
在对artmethod执行前后进行hook时 这里涉及到处理art方法解释执行的三种情况。
ART Runtime 解释器
The C++ interpreter,也就是传统的基于switch结构的解释器。一般仅在调试环境、方法跟踪、指令不支持或者在字节码发生异常情况下(例如failed structured-locking verification)才走该分支。The mterp fast interpreter,核心是引入了handler table做指令映射,并通过手写汇编以实现指令间的快速切换,提高了解释器性能。Nterp是Mterp的再次优化。Nterp省去了managed code stacks的维护,采用了和Native方法一样的栈帧结构,并且译码和翻译执行全程都由汇编代码实现,进一步拉进解释器和compiled code的性能差距。在这边我发现了一个异常现象,就是Android 14的解释执行居然都用的switch解释执行方式。我又重新去测试了几个Android 版本的解释执行方式。Android 12走的mterp,Android 13走的是nterp,当进行调试的时候才会走到switch, 理论上Android 14应该也走nterp才对,怎么会走了最慢的switch呢。以下按顺序是12、13、14版本的方法执行backtrace。
排查怀疑点
开始怀疑是解释执行导致的卡顿了,翻了下源码 art/runtime/interpreter/mterp/nterp.cc 中确实有变动 如果是javaDebuggable 就不走nterp了。接下来尝试去证明是是这个问题导致的。
isJavaDebuggable 是runtime.cc中的 RuntimeDebugState runtime_debug_state_ 中控制的。我们可以找到runtime的实例然后通过偏移量修改过runtime_debug_state_属性,看了下源码还可以通过_ZN3art7Runtime20SetRuntimeDebugStateENS0_17RuntimeDebugStateE 进行设置。
四
最后
最近在社区上也看到了高通工程师的一篇文章,他在我定位到的问题的基础上做了更详细的分析。确认了Google会在Android 15上修复这个问题,如果是海外版本的Android 14设备,Google计划通过com.android.artapex模块的更新来修复这个问题。但是国内由于网络的问题,Google的推送无法工作,因此需要各个手机厂家来主动合入这两笔改动。[1]
如果大家需要临时解决debugable包的卡顿的问题也可以通过上述方式解决。
参考文章:
[1] https://juejin.cn/post/7353106089296789556
作者:乌柚
来源-微信公众号:得物技术
出处:https://mp.weixin.qq.com/s/qVaQKa90QiKIQg8XRATUTA
相关资讯
更多+2024-01-31
2024-04-23
2024-06-02
2024-06-17
2024-07-15
2024-06-25
2024-03-21
2024-09-14
2024-01-14
2024-03-13
Copyright © 2009-2025 m.fsktgsy.com
网站地图