优化-ANR

ANR提问
官方文档

  1. 什么是 ANR?
  2. 系统是如何设计 ANR 的?
  3. 发生 ANR 时系统都会获取哪些信息以及工作流程?
  4. 导致 ANR 的原因有哪些?
  5. 遇到这类问题该如何分析?
  6. 如何能更加快速准确的定位问题?
  7. 面对这类问题我们能主动做些什么?

ANR思考

  1. ANR是系统对Activity,Service,Input,BroadCastReceiver等组件的超时监控,对超时抛出异常。
  2. 系统有很多服务启动监控,在超时时间内完成任务会关闭监控,没完成则触发超时报警。
  3. ANR时,系统会捕获当前运行线程的堆栈信息,执行的快照信息,获取和当前线程交互的服务进程的信息,当前活跃进程的信息。

卡顿问题分析指标

1. 线程cpu使用率/线程堆栈信息

1.系统整体cpu使用信息
cat /proc/stat
2.进程cpu使用信息
cat /proc/[pid]/stat

使用率计算
利用信息整理出自定义log,类比trace log(系统进程信息+线程堆栈信息)
案例:解析系统信息打印到log文件

2.获取线程对战堆栈信息:
Thread.getStackTrace()
Thread.getAllStackTraces()
案例

2.trace log 分析

线程状态信息,Java定义的6中线程状态对应Native线程的状态:
线程状态资料

// download-common-49 代表线程名称
// prio = 优先级  
// Native = 代表当前线程的状态,Native代表执行JNI代码
"download-common-49" prio=5 tid=62 Waiting
//group是线程组名称 sCount是线程被挂起的次数 dsCount是线程调试状态下挂起的次数
//obj是这个线程的Java对象的地址 self表是这个线程Native的地址。
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x133c32b0 self=0x6ead411c00
  // sysTid 是此线程在内核中对应的线程ID 
// nice 代表着struct_task任务被调度的优先级
// cgrp是调度组 sched分别是线程的调度策略和优先级 handle是线程的处理函数地址。
  | sysTid=22035 nice=10 cgrp=default sched=0/0 handle=0x6ec1dacd50
  //state = native 线程状态 schedstat值来自于/proc/[pid]/task/[tid]/schedstat,分别是cpu上执行的时间、线程的等待时间和线程执行的时间片
// utm是线程用户态下执行时间 stm是内核态下执行时间(单位是jiffies,执行IO等操作才会切换到内核态)  HZ可推出执行时间
  | state=S schedstat=( 43132810 109269790 129 ) utm=1 stm=3 core=3 HZ=100
  | stack=0x6ec1caa000-0x6ec1cac000 stackSize=1039KB
  | held mutexes=
  at java.lang.Object.wait(Native method)
  - waiting on <0x00b6662f> (a java.lang.Object)
  at java.lang.Object.wait(Object.java:442)
  at java.lang.Object.wait(Object.java:568)
  at com.tencent.qqmusic.qzdownloader.downloader.impl.b.r(SourceFile:142)
  - locked <0x00b6662f> (a java.lang.Object)
  at com.tencent.qqmusic.qzdownloader.downloader.impl.b.a(SourceFile:652)
  at com.tencent.qqmusic.qzdownloader.downloader.impl.b.b(SourceFile:339)
  at com.tencent.qqmusic.qzdownloader.downloader.impl.b.a(SourceFile:233)
  at com.tencent.qqmusic.qzdownloader.downloader.impl.d.a(SourceFile:35)
  at com.tencent.qqmusic.qzdownloader.downloader.impl.DownloadTask.a(SourceFile:263)
  at com.tencent.qqmusic.qzdownloader.downloader.impl.DownloadTask.run(SourceFile:54)
  at com.tencent.qqmusic.module.common.thread.h.run(SourceFile:55)
  at java.util.concurrent.ThreadPoolExecutor.processTask(ThreadPoolExecutor.java:1187)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  at java.lang.Thread.run(Thread.java:929)
  at com.tencent.qqmusic.module.common.thread.c$1.run(SourceFile:35)

锁信息案例:

"OkHttp ConnectionPool" daemon prio=5 tid=41 TimedWaiting
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x133c04e8 self=0x6f31ff8400
  | sysTid=8743 nice=0 cgrp=default sched=0/0 handle=0x6ec2f5bd50
  | state=S schedstat=( 69290105 74527077 261 ) utm=2 stm=4 core=3 HZ=100
  | stack=0x6ec2e59000-0x6ec2e5b000 stackSize=1039KB
  | held mutexes=
  at java.lang.Object.wait(Native method)
  - waiting on <0x0e321c0e> (a com.android.okhttp.ConnectionPool)
  at com.android.okhttp.ConnectionPool$1.run(ConnectionPool.java:106)
  - locked <0x0e321c0e> (a com.android.okhttp.ConnectionPool)
  at java.util.concurrent.ThreadPoolExecutor.processTask(ThreadPoolExecutor.java:1187)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1152)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  at java.lang.Thread.run(Thread.java:929)

3.systrace/Perfetto使用

Android系统跟踪概览
了解systrace
ftrace
atrace
介绍
systrace只能跟踪系统API,如果想确定应用中调用的函数执行时间,需要自定义事件,使用函数插桩在函数执行开始和结束分别调用:

Trace.beginSection("方法名")
...
Trace.endSection()

自定义trace事件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值