会造成ANR的场景:
ANR问题分析步骤
1. 确认友商
如果是三方应用的anr问题且必现问题或高概率发生,先确认原生机是否可以同样复现,以及友商手机可否复现,分为 4 种情况。如果判断为三方应用的问题,可转三方质量商务处理并适当贴一些原因分析。
1.1 三方应用情况分类
我司 | 原生Pixel | 友商 | 决策 |
有 | | | 解决 |
有 | 有 | | 三方解决+评审是否做适配 |
有 | | 有 | 评审是否解决(少见) |
有 | 有 | 有 | 三方解决+评审是否做适配 |
2. 确认问题发生时间点找到log对应位置分析
打开ems_logs/zipLog,找到问题发生对应时间的那份ANR解压打开进行log分析如
APP_ANR@22439_com.gotokeep.keep_2023-05-05-19-17-16.808.txt
或FATAL_2023-05-05-19-17-16 / anr_2023-01-24-15-47-00-907文件
或23-05-06--10-39-05_recording / mobile / main.log(logcat/main.log)中查询 “ActivityManager: ANR in”
或23-05-06--10-39-05_recording / mobile / event.log(logcat/event.log)中查询 “am_anr”
2.1 log特殊分析情况
(案例)
如以下微信语音通话同时播放音乐,反复开关扬声器,会导致系统崩溃的问题
Plain Text ----- pid 32167 at 2023-01-24 15:47:00.983416988+0800 ----- Cmd line: com.android.systemui ......
"main" prio=5 tid=1 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x72b41528 self=0xb4000079cb2bf380 | sysTid=32167 nice=0 cgrp=foreground sched=0/0 handle=0x7b958c64f8 | state=S schedstat=( 8059148030 8008439373 22623 ) utm=609 stm=196 core=6 HZ=100 | stack=0x7ff826a000-0x7ff826c000 stackSize=8188KB | held mutexes= native: #00 pc 00000000000a5b8c /apex/com.android.runtime/lib64/bionic/libc.so (__ioctl+12) (BuildId: 2938f6235116cbc48464ee0f7622625e) native: #01 pc 000000000005c9e0 /apex/com.android.runtime/lib64/bionic/libc.so (ioctl+160) (BuildId: 2938f6235116cbc48464ee0f7622625e) native: #02 pc 000000000005c2a0 /system/lib64/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+284) (BuildId: b5f24c77eb4cb8038980e4e1f81dcfc0) native: #03 pc 000000000005d4fc /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+76) (BuildId: b5f24c77eb4cb8038980e4e1f81dcfc0) native: #04 pc 000000000005d238 /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+224) (BuildId: b5f24c77eb4cb8038980e4e1f81dcfc0) native: #05 pc 0000000000054a44 /system/lib64/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+192) (BuildId: b5f24c77eb4cb8038980e4e1f81dcfc0) native: #06 pc 0000000000176b98 /system/lib64/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+212) (BuildId: 958e4dab31a35b8c82656bf5f30a2d95) at android.os.BinderProxy.transactNative(Native method) at android.os.BinderProxy.transact(BinderProxy.java:584) atandroid.media.IAudioService$Stub$Proxy.getStreamVolume(IAudioService.java:3909) at android.media.AudioManager.getStreamVolume(AudioManager.java:1231) atcom.flyme.systemui.volume.QSVolumeControllerImpl.getStreamVolume(QSVolumeControllerImpl.kt:265) atcom.flyme.systemui.volume.QSVolumeControllerImpl.access$getStreamVolume(QSVolumeControllerImpl.kt:43) at com.flyme.systemui.volume.QSVolumeControllerImpl$mCommunicationDeviceChangedListener$2$1.onCommunicationDeviceChanged(QSVolumeControllerImpl.kt:93) ...... |
结论:
可见是com.flyme.systemui.volume.QSVolumeControllerImpl.getStreamVolume跨进程调用到AudioService的getStreamVolume里面卡住了,那问题就是systemui主线程频繁调用getStreamVolume导致 或 AudioService的getStreamVolume本身有问题导致。显然前者非原生,发生问题的概率更大。后续解决方案没有修改业务逻辑,但在systemui调用getStreamVolume获取音量之间添加了一个cache.java,里面存放一些情况下不变的值用于直接获取而不是频繁从AudioService获取来解决问题。
当然应用也可以尝试把此访问业务放到子线程里做事,只不过这里涉及到主线程UI的实时更新不方便。
(如果认为证据少,也可以通过找binder对端的方法说明资源正在被谁占用导致systemui卡住,不过比较繁琐)就用本例来找以下binder对端。
2.1.1 binder找对端
(在anrlog中搜索Blocked也可以发现是具体卡在了哪里如下)
Plain Text "main" prio=5 tid=1 Blocked | group="main" sCount=1 ucsCount=0 flags=1 obj=0x72b41528 self=0xb4000079cb2bf380 | sysTid=2719 nice=-2 cgrp=foreground sched=0/0 handle=0x7b958c64f8 | state=S schedstat=( 51445309149 81742345474 421858 ) utm=3031 stm=2113 core=2 HZ=100 | stack=0x7ff826a000-0x7ff826c000 stackSize=8188KB | held mutexes= at com.android.server.audio.AudioService.getDeviceSetForStream(AudioService.java:7041) - waiting to lock <0x01384d82> (a java.lang.Class<com.android.server.audio.AudioService$VolumeStreamState>) held by thread 110 at com.android.server.audio.AudioService.getDeviceForStream(AudioService.java:6948) at com.android.server.audio.AudioService.getStreamVolume(AudioService.java:4760) at android.media.AudioManager.getStreamVolume(AudioManager.java:1231) ...... |
搜索2719可知是卡在了system_server
Plain Text ----- pid 2719 at 2023-01-24 15:47:01.675316363+0800 ----- Cmd line: system_server ...... |
在同文件夹下的binderinfo文件中搜索systemui的pid 32167
SQL outgoing transaction 8372988: 0000000000000000 from 32167:32167 to2719:5009 code 12 flags 10 pri 0:120 r1 incoming transaction 8372988: 0000000000000000 from 32167:32167 to2719:5009 code 12 flags 10 pri 0:120 r1 node 11752 size 76:0 data 0000000000000000 |
可知此时systemui正在和system_server通信
在anrlog中5009线程可知:
SQL "binder:2719_E" prio=5 tid=180 Blocked | group="main" sCount=1 ucsCount=0 flags=1 obj=0x1388d458 self=0xb4000079cb46c930 | sysTid=5009 nice=0 cgrp=foreground sched=0/0 handle=0x775456acb0 | state=S schedstat=( 13630495183 12263926909 72029 ) utm=861 stm=501 core=0 HZ=100 | stack=0x7754473000-0x7754475000 stackSize=991KB | held mutexes= at com.android.server.audio.AudioDeviceBroker.isDeviceOnForCommunication(AudioDeviceBroker.java:513) - waiting to lock <0x07d20c85> (a java.lang.Object) held by thread 111 at com.android.server.audio.AudioDeviceBroker.isBluetoothScoOn(AudioDeviceBroker.java:568) at com.android.server.audio.AudioService.isBluetoothScoOn(AudioService.java:6143) at android.media.IAudioService$Stub.onTransact(IAudioService.java:2164) at android.os.Binder.execTransactInternal(Binder.java:1285) at android.os.Binder.execTransact(Binder.java:1244) system_server的binder对端2719_E线程中isBluetoothScoOn正在被调用,但其锁0x07d20c85被线程111占用了, "AudioDeviceBroker" prio=5 tid=111 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x13889128 self=0xb4000079cb3c3f60 | sysTid=3454 nice=0 cgrp=foreground sched=0/0 handle=0x773a719cb0 ...... at com.android.server.audio.AudioDeviceBroker$BrokerHandler.handleMessage(AudioDeviceBroker.java:1477) - locked <0x05f1adfc> (a java.lang.Object) - locked <0x07d20c85> (a java.lang.Object) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at com.android.server.audio.AudioDeviceBroker$BrokerThread.run(AudioDeviceBroker.java:1331) |
在同文件夹下的binderinfo文件中搜索3534
SQL outgoing transaction 8379166: 0000000000000000 from 2719:3454 to1643:26372 code 51 flags 10 pri 0:120 r1 incoming transaction 8379166: 0000000000000000 from 2719:3454 to1643:26372 code 51 flags 10 pri 0:120 r1 node 10250 size 140:0 data 0000000000000000 |
可知此时system_server的这个binder线程正在和1643进程的26372线程通信,在anrlog中搜索1643
SQL ----- pid 1643 at 2023-01-24 15:47:04.702978758+0800 ----- Cmd line: /system/bin/audioserver |
此时system_server的这个binder线程正在和通信,system_server不选择使用其他binder线程的原因估计是其进程的binder线程数量耗尽了。
继续搜索26372线程
SQL "binder:1643_B" sysTid=26372 #00 pc 000000000004ea70 /apex/com.android.runtime/lib64/bionic/libc.so (syscall+32) (BuildId: 2938f6235116cbc48464ee0f7622625e) #01 pc 0000000000053458 /apex/com.android.runtime/lib64/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+148) (BuildId: 2938f6235116cbc48464ee0f7622625e) #02 pc 00000000000b9934 /apex/com.android.runtime/lib64/bionic/libc.so (pthread_cond_timedwait+140) (BuildId: 2938f6235116cbc48464ee0f7622625e) #03 pc 000000000004ecb0 /system/lib64/libaudiopolicyservice.so (android::AudioPolicyService::AudioCommandThread::sendCommand(android::sp<android::AudioPolicyService::AudioCommandThread::AudioCommand>&, int)+320) (BuildId: 67a27d80d1c32888be575cc15b943518) |
可知锁被占用在audiopolicyservice内调用AudioPolicyService::AudioCommandThread::sendCommand处,此处是原生代码,属于正常耗时流程。
所以还是需要systemui在调用处做优化。
(案例)
Keep app点击运动开始后息屏静置,再点击停止发生不成功的activity跳转(OutdoorTrainingV2Activity跳转到Maictivity),Keep应用的OutdoorWorkoutBackgroundService调用onDestroy,走到了
/system/bin/mediaserver 的MediaPlayer.java
——> tryToDisableNativeRoutingCallback
——> testDisableNativeRoutingCallbacksLocked
——> native_enableDeviceCallback
——> 到JNI底层长时间未完成跳出,耗时超过5秒触发anr
2.1.2 trace文件分析
也可以通过把log里的trace文件上传到谷歌的perfettoUI网址https://www.ui.perfetto.dev/#!/record/instructions中分析。如上面的案例:
后续发现是mediaservice里我们写了一段“同步”代码导致,取消同步不阻塞调用audio write,问题即可解决。
2.1.3 Anr日志文件无效
PHP "main" prio=5 tid=1 Native | group="main" sCount=1 dsCount=0 obj=0x7685ba50 self=0x7fb0840a00| sysTid=1460 nice=-10 cgrp=default sched=0/0 handle=0x7fb4824aa0| state=S schedstat=( 213445473008 99617457476 724519 ) utm=14518 stm=6826 core=0 HZ=100| stack=0x7fe82c6000-0x7fe82c8000 stackSize=8MB| held mutexes= kernel: __switch_to+0x70/0x7c kernel: SyS_epoll_wait+0x2d4/0x394 kernel: SyS_epoll_pwait+0xc4/0x150 kernel: el0_svc_naked+0x24/0x28 native: #00 pc 000000000001bf2c /system/lib64/libc.so (syscall+28) native: #01 pc 00000000000e813c /system/lib64/libart.so (_ZN3art17ConditionVariable16WaitHoldingLocksEPNS_6ThreadE+160) native: #02 pc 000000000054b6f8 /system/lib64/libart.so (_ZN3artL12GoToRunnableEPNS_6ThreadE+328) native: #03 pc 000000000054b56c /system/lib64/libart.so (_ZN3art12JniMethodEndEjPNS_6ThreadE+28) native: #04 pc 00000000008ccc50 /system/framework/arm64/boot-framework.oat (Java_android_os_MessageQueue_nativePollOnce__JI+156) at android.os.MessageQueue.nativePollOnce(Native method) at android.os.MessageQueue.next(MessageQueue.java:323) |
3. 尝试复现问题(测试提供的log不足)
3.1 整机状态良好的情况下复现了问题
APP_ANR文件中搜索“main”,查看发生anr时此刻主线程堆栈,通常来说,如果打印的堆栈是该进程内部的堆栈,并且经过业务证实这段代码确实可能存在耗时,那么可以给三方商务根据callstack位置找到代码修改即可,如果友商适配了此问题也可以考虑看我司能否适配。(这种问题一般属于严重三方问题)
(案例)
下图为美团滑动anr问题
SQL Process: com.sankuai.meituan PID: 32180 UID: 10214 Frozen: false Flags: 0x38b83e44 Package: com.sankuai.meituan v1200090209 (12.9.209) Foreground: Yes Process-Runtime: 91290258 Activity: com.sankuai.meituan/com.dianping.live.live.mrn.MLiveMRNActivity ErrorId: 8dd92ab2-c430-44a2-a68b-7a34b77d7cdd Build: meizu/meizu_20Pro_CN/meizu20Pro:13/TKQ1.221114.001/1673297425:user/release-keys Loading-Progress: 1.0 Dropped-Count: 0 ShouldUpload: true ZipLogFile: /data/misc/ems_logs/zipLog/APP_ANR@32180_com.sankuai.meituan_2023-04-25-20-32-03.319.zip
Input dispatching timed out (492e397 com.sankuai.meituan/com.dianping.live.live.mrn.MLiveMRNActivity (server) is not responding. Waited 5001ms for FocusEvent(hasFocus=true)) ==================================================================================================== ----- Output from /proc/pressure/memory ----- some avg10=0.00 avg60=0.03 avg300=0.12 total=140081266(占140M并不高 full avg10=0.00 avg60=0.00 avg300=0.00 total=110897319 ----- End output from /proc/pressure/memory -----
----- Output from /proc/pressure/cpu ----- CPU usage from 0ms to 5808ms later (2023-04-25 20:31:57.475 to 2023-04-25 20:32:03.283): 155% 32180/com.sankuai.meituan: 133% user + 21% kernel / faults: 19145 minor 944 major 67% 2867/system_server: 30% user + 36% kernel / faults: 70692 minor 181 major 51% 1649/vendor.qti.hardware.display.composer-service: 11% user + 40% kernel / faults: 1288420 minor 33% 3926/com.android.systemui: 20% user + 13% kernel / faults: 2978 minor 42 major 30% 1773/surfaceflinger: 18% user + 12% kernel / faults: 3675 minor 1 major ...... 0.1% 31679/system-log: 0% user + 0.1% kernel 0.1% 32211/com.flyme.systemuiex: 0% user + 0.1% kernel / faults: 1 minor +0% 7191/kworker/6:0: 0% user + 0% kernel 67% TOTAL(负载不算太高: 36% user + 28% kernel + 0.2% iowait + 2.1% irq + 0.3% softirq ...... "main" prio=5 tid=1 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x72f7f548 self=0xb400007bb6042c00 | sysTid=32180 nice=0 cgrp=background sched=0/0 handle=0x7c5b0a14f8 | state=S schedstat=( 7273443913 816442287 15156 ) utm=578 stm=149 core=0 HZ=100 | stack=0x7fcb618000-0x7fcb61a000 stackSize=8188KB | held mutexes= native: #00 pc 0000000000089630 /apex/com.android.runtime/lib64/bionic/libc.so (syscall+32) (BuildId: c7a69636ad70437896f8f6cfecde9001) native: #01 pc 000000000008e018 /apex/com.android.runtime/lib64/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+148) (BuildId: c7a69636ad70437896f8f6cfecde9001) native: #02 pc 00000000000f43dc /apex/com.android.runtime/lib64/bionic/libc.so (pthread_cond_wait+80) (BuildId: c7a69636ad70437896f8f6cfecde9001) native: #03 pc 000000000028a06c /system/lib64/libhwui.so (android::uirenderer::renderthread::DrawFrameTask::drawFrame()+360) (BuildId: 46f2295089591c6e67e210338c5b1e07) at android.graphics.HardwareRenderer.nSyncAndDrawFrame(Native method) at android.graphics.HardwareRenderer.syncAndDrawFrame(HardwareRenderer.java:466) at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:810) at android.view.ViewRootImpl.draw(ViewRootImpl.java:4647) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4358) ...... |
(看堆栈在graphics表明可能是其反复调用绘制导致),后续美团更新解决了。
(案例)
案发时间点附近,发现大量的GC片段且很多GC耗时都较长,Clamp target GC heap from说明当前应用堆使用已超出上限512M,为了满足新分配的对象内存需求,调整目标堆上限值,且系统一直持续不断的对该应用进行阻塞GC(GC分为不同力度,阻塞GC说明应用此时内存情况比较糟糕),尽管应用持续不断的阻塞GC,应用内存依旧没有降下来。这种情况下很可能是出现了应用内存泄漏的情况。
3.1.1 发生anr的进程占比很高
那要让此应用看下原因,如此处的 155% 32180/com.sankuai.meituan。很可能是应用在做耗时操作,频繁绘制、网络访问、读取文件等。有时候可能会打印_futex_wait_ex 如
SQL "main" prio=5 tid=1 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x7169d2a8 self=0xb40000767d242c00 | sysTid=29357 nice=-20 cgrp=top-app sched=1073741825/1 handle=0x772cdd84f8 | state=S schedstat=( 3300558764759 160006040018 5764104 ) utm=239875 stm=90180 core=3 HZ=100 | stack=0x7fdeca9000-0x7fdecab000 stackSize=8188KB | held mutexes= native: #00 pc .../apex/com.android.runtime/lib64/bionic/libc.so (syscall+32) (BuildId: c7a69636ad70437896f8f6cfecde9001) native: #01 pc .../apex/com.android.runtime/lib64/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+148) (BuildId: c7a69636ad70437896f8f6cfecde9001) |
3.1.2 通过同时其他进程的负载状况推测出应用的什么逻辑卡住了
如另外当出现大量的 IO 操作的时候,应用主线程的 Uninterruptible Sleep 也会变多,此时涉及到 io 操作(比如 view ,读文件,读配置文件、读 odex 文件),都会触发 Uninterruptible Sleep , 导致整个操作的时间变长。
3.1.3 直接看下系统日志,可能是应用的内存使用导致的问题
关于应用内存使用不当,通常有如下几种情况,这些情况虽不一定会导致ANR,但是应用操作上的卡顿可能在所难免,log关键词GC Alloc。
-
频繁的生成临时对象导致堆内存增长迅速
-
达到下次堆GC触发阈值后便会触发Bg GC,进而导致回收线程跑大核和前台应用争抢CPU。
-
另外GC回收阶段会存在一次锁堆
-
此时应用的主线程会被pause,这种情况下势必会造成应用使用卡顿甚至ANR。
-
应用发生了较为严重的内存泄漏
-
此种情况比较常见,会导致GC一直无法回收足够的内存,可以log搜索关键词证明,也可以通过Android Studio的Profiler工具直接进行观测到应用占用内存不断增长。
-
应用申请大内存触发阻塞GC
-
以便应用能够申请到足够的内存,但这种情况通常会引起应用界面的黑屏或者明显的卡顿。
-
应用调用显式GC接口即System.gc()
-
我们知道系统低内存时会触发OnTrimMemory回调,如果应用在OnTrimMemory中并且是在主线程中直接调用显式GC接口即System.gc(),也容易引起应用卡顿,对于这个接口的使用需要谨慎。
-
还可以看am_pss打印的进程资源状态如
-
I am_pss : [29357,10304,com.tencent.mm,1445406720,980193280,411634688,1198116864,1,10,87]说明当时微信的内存占比比较高(1.445G),系统很可能处于低内存状态。
3.1.4 通过perfettoUI分析
此时最需要跑的当前进程是否是跑到了非超大核上(cpu7一般是超大核,另外好的芯片还会有两个大核、中核,序号依次变小);以及现在手机cpu正在做什么耗时的操作如绘制类图样和渲染器(graphics、renderer);或者可能是因为应用导致了系统需要频繁的GC,导致GC的程序跑到了大核上等。
3.1.5 binder阻塞的情况往往是binder耗尽
应用最多支持16个binder 线程,SystemServer支持最多32个binder 线程。
举个例子,进程A短时间内发送很多Binder 请求给进程B,这种情况下就有可能会导致在短时间内,接收端进程B的 Binder 线程池中的16个Binder线程,都用来响应进程A的Binder请求,也就是我们常说的Binder线程池耗尽的情况,此时进程B无法处理进程A发过来的新的Binder请求。如:
SQL 行 19: ----- pid 32167 at 2023-01-24 15:47:00.983416988+0800 ----- 行 250: | sysTid=32167 nice=0 cgrp=foreground sched=0/0 handle=0x7b958c64f8 行 370: "binder:32167_1" prio=5 tid=13 Native 行 388: "binder:32167_2" prio=5 tid=14 Native 行 406: "binder:32167_3" prio=5 tid=15 Native 行 424: "binder:32167_4" prio=5 tid=16 Native 行 632: "HwBinder:32167_1" prio=5 tid=31 Native 行 698: "binder:32167_5" prio=5 tid=18 Native 行 716: "binder:32167_6" prio=5 tid=35 Native 行 734: "binder:32167_7" prio=5 tid=36 Native 行 752: "binder:32167_8" prio=5 tid=37 Native 行 786: "binder:32167_9" prio=5 tid=39 Native 行 804: "binder:32167_A" prio=5 tid=40 Native 行 892: "binder:32167_B" prio=5 tid=45 Native 行 910: "binder:32167_C" prio=5 tid=46 Native 行 1143: "binder:32167_D" prio=5 tid=3 Native 行 1177: "binder:32167_E" prio=5 tid=60 Native 行 1195: "binder:32167_F" prio=5 tid=63 Native 行 1566: "binder:32167_2" prio=5 (not attached) 行 1762: ----- end 32167 ----- |
关于Binder耗尽的情况,通常是由于代码设计上的缺陷,导致短时间内高频发起Binder;也有可能是好几个应用同时在对同一个进程如systemserver发起binder调用;还有一种情况也可能会出现,那就是在Monkey测试环境下。
3.2 只能在高负载情况下才能复现问题
(案例)
如下为systemui问题,高负载场景(用户反馈的log
SQL Process: com.android.systemui PID: 7688 UID: 10090 Frozen: false Flags: 0x38c8be0d Package: com.android.systemui v10001000 (10.1.0) Foreground: No Process-Runtime: 135945 ErrorId: d548b2d2-c720-4d86-bbc5-003dda4158b8 Build: meizu/meizu_18Pro_CN/meizu18Pro:13/TKQ1.221114.001/1681589413:user/release-keys Loading-Progress: 1.0 Dropped-Count: 0 ShouldUpload: true ZipLogFile: /data/misc/ems_logs/zipLog/APP_ANR@7688_com.android.systemui_2023-04-20-19-30-55.031.zip Input dispatching timed out (3c2477c NotificationShade (server) is not responding. Waited 5000ms for MotionEvent) ...... CPU usage from 34ms to -9667ms ago (2023-04-20 19:30:45.266 to 2023-04-20 19:30:54.967): 103% 1518/system_server: 45% user + 58% kernel / faults: 72387 minor 47 major 38% 1055/surfaceflinger: 23% user + 14% kernel / faults: 2773 minor 15% 13091/com.sup.android.superb: 11% user + 4.4% kernel / faults: 32108 minor 98 major ...... +0% 16709/logcat: 0% user + 0% kernel 92% TOTAL: 52% user + 36% kernel + 0.3% iowait + 2.5% irq + 0.7% softirq |
比如此处92% TOTAL表明高负载,分析top前5看下谁占用系统资源比较多,看属于是正常占用还是异常.
高负载下一般要分情况:
3.2.1 低内存时系统往往会竭尽可能的回收内存
可能触发的fast path 回收 \ kswapd 回收 \ direct reclaim 回收 \ LMK杀进程回收等行为,都会造成do_page_fault 高频发生,log中也会有大量lowmemorykiller打印。所以,分析ANR问题时如果遇到kswapd占据很高(top3),则认为该问题受系统低内存影响很大。
3.2.2 看是否和系统的优化冻结有关
在anr文件中看 “Frozen: false” 处是否为true,移交冻结伙伴看是否是不合理的冻结或未解冻导致。
3.2.3 受环境温度或负载影响
手机温度较高,也会触发温控,但一般是结果而不是造成anr的原因。(在提供的日志文件中 找到kernel 搜索THERMGRP关键字,默认这个是20s查询一次 如果需要排查的更精细,echo 5 > /sys/class/meizu/mz_timestamp/timestamp_intv 这个命令可以修改为5s一次。
[cpu温度 PCB温度 GPU温度 小核当前频率 大核当前频率 超大频率 GPU当前频率 电流]
对比机器的配置文件或直接输入 adb shell thermal-engine-v2 -o 可以看到一份配置信息
且在/vendor/etc/下的thermal.xxx.conf文件 有更多的关于cpu频率的配置信息(其中mid-普通,game-游戏,super-高帧率游戏)如:
3.2.4 有其他应用或进程占据较高的负载
可能是由于其导致的io、media、震动等资源的占用,发生anr的应用只不过是替罪羊。