卡顿介绍及优化工具选择
CPU Profiler
Systrace
StrictMode
背景介绍
很多性能问题不易被发现,但是卡顿很容易被直观感受
卡顿问题难以定位
卡顿问题难在哪里
产生原因错综复杂:代码、内存、绘制、IO?
不易复现:当时场景强相关
CPU Profiler
图形展示执行时间、调用栈
信息全面,包含所有线程
运行时开销严重,整体都会变慢(带偏优化方向)
StrictMode
严苛模式,Android提供的一种运行时检测机制
方便强大,容易被忽略
包含:线程策略和虚拟机策略检测
线程策略:
自定义的耗时操作,detectCustomSlowCalls()
磁盘读取操作,detectDiskReads
网络请求,detectNetwork
虚拟机策略:
Activity泄漏,detectActivityLeaks()
Sqlite对象泄漏,detectLeakedSqlLiteObjects()
检测实例数量,setClassInstanceLimit()
自动化卡顿检测方案及优化
自动化卡顿检测方案原理
为什么需要自动化检测方案?
- 系统工具适合线下针对性分析
- 线上及测试环节需要自动化检测方案
方案原理
- 消息处理机制,一个线程只有一个Looper
- mLogging对象在每个message处理前后被调用
- 主线程发生卡顿,实在dispatchMessage执行耗时操作
具体实现
- Looper.getMainLooper().setMessageLogging();
- 匹配>>>>Dispatching,阈值时间后执行任务(获取堆栈信息)
- 匹配<<<<Finished,任务启动之前取消掉
AndroidPerformanceMonitor
- 非侵入式的性能监控组件,通知形式弹出卡顿信息
- com.github.markzhai:blockcanary-android
- https://github.com/markzhai/AndroidPerformanceMonitor
BlockCanary.install(this,new BlockCanaryContext()).start();
方案总结
- 非侵入式
- 方便精准,定位到代码的某一行
自动化检测方案问题
- 确实卡顿了,但是卡顿堆栈可能不准确
- 和OOM一样,最后的堆栈只是表象,不是真正问题
自动检测方案优化
- 获取监控周期内的多个堆栈,而不是最后一个
- startMonitor->高频采集堆栈->endMonitor->记录多个堆栈->上报
海量卡顿堆栈处理
- 高频卡顿上报太大,服务端有压力
- 分析:一个卡顿下多个堆栈大概率有重复
- 解决:对一个卡顿下堆栈进行hash排重,找出重复堆栈
- 效果:极大的减少展示量同时更高效找到卡顿堆栈
总结
自动化卡顿检测方案
问题及优化思路
ANR分析与实战
ANR介绍与实战
KeyDispatchTimeout,5s
BroadcastTimeout,前台10s,后台60s
ServiceTimeout,前台20s,后台200s
具体参考ActivityManagerService类信息
ANR 执行流程
发生ANR
进程接受异常终止信号,开始写入进程ANR信息
弹出ANR提示框(Rom表现不一)
ANR 解决套路
adb pull data/anr/trace.txt 存储路径
详细分析:CPU、IO、锁冲突
锁冲突举例
new Thread(){
public void run(){
super.run();
synchronized (MainActivity.this){
Tread.sheep(20000)
}
}
}
synchronized(MainActivity.this){
print
}
adb pull data/anr/trace.txt
线上ANR监控方案
- 通过FileOberver监控文件变化,高版本权限问题
ANRWatch-Dog原理及实战
非侵入式的ANR监控组件
com.github.anrwatchdog:anrwatchdog:1.3.0
https://github.com/SalomonBrys/ANR-WatchDog
启动ANRWatch-Dog
new ANRWatchDog().start();
核心代码
@Override
public void run() {
setName("|ANR-WatchDog|");
int lastTick;
int lastIgnored = -1;
while (!isInterrupted()) {
lastTick = _tick;
_uiHandler.post(_ticker);
try {
Thread.sleep(_timeoutInterval);
}
catch (InterruptedException e) {
_interruptionListener.onInterrupted(e);
return ;
}
// If the main thread has not handled _ticker, it is blocked. ANR.
if (_tick == lastTick) {
if (!_ignoreDebugger && Debug.isDebuggerConnected()) {
if (_tick != lastIgnored)
Log.w("ANRWatchdog", "An ANR was detected but ignored because the debugger is connected (you can prevent this with setIgnoreDebugger(true))");
lastIgnored = _tick;
continue ;
}
ANRError error;
if (_namePrefix != null)
error = ANRError.New(_namePrefix, _logThreadsWithoutStackTrace);
else
error = ANRError.NewMainOnly();
_anrListener.onAppNotResponding(error);
return;
}
}
}
WatchDog
原理
start->post消息改值->sleep->检测是否修改->判断ANR发生
方案总结
非侵入式
弥补高版本无权限
结合使用
区别
AndroidPerformanceMonitor:监控Msg
ANR-WatchDog:看最终结果
前者适合监控卡顿,后者适合补充ANR监控
卡顿单点问题监测方案
背景介绍
自动卡顿检测方案并不够
体系化解决方案必须尽早暴露问题
单点问题:主线程IPC,DB
IPC问题检测
监控指标
IPC调用类型
调用耗时,次数
调用堆栈,发生线程
常规方案
IPC前后埋点
不够优雅,容易忘记
维护成本大
IPC问题监测技巧
adb命令
- adb shell am trace-ipc start
- adb shell am trace-ipc stop -dump-file /data/local/tmp/ipc-trace.txt
- adb pull /data/local/tmp/ipc-trace.txt
优雅方案
- ARTHook还是ApsectJ?
- ARTHook:可以Hook系统方法
- AspectJ:非系统方法
卡顿问题监测方案
利用ARTHook完善线下工具
开发阶段Hook相关操作,暴露、分析问题
监控纬度
IPC
IO、DB
View绘制
如何实现界面秒开
界面秒开实现
- 界面秒开是一个小的启动优化
- 可以借鉴启动优化及布局优化
- Systrace,优雅异步+优雅延迟初始化
- 异步Infalte、X2C、绘制优化
- 提前获取页面数据
界面秒开率统计
- onCreate到onWindowFocusChanged
- 特定接口
Lancet
轻量级AndroidAOP框架
- 编译速度快,支持增量编译
- API简单,没有任何多余代码插入APK
- @Proxy通常用于对系统API调用的Hook
- @Insert通常用于操作App于Library的类
界面秒开监控纬度
总体耗时
生命周期耗时
生命周期间隔耗时
总结
界面秒开实现方案
界面秒开率统计
Lancet介绍与实战
优雅监控耗时盲区
背景
生命周期间隔
onResume到Feed展示时间间隔
举例:postMessage,很可能在Feed之前执行
监控难点
只知道盲区时间,不清楚具体在做什么
线上盲区无从排查
线下方案
TraceView
特别适合一段时间内的盲区监控
线程具体时间做了什么,一目了然
线上方案
思考:
所有方法都是Msg,mLoging?没有Msg具体堆栈
AOP切Handler方法?不清楚准确执行时间
使用统一Handler:定制具体方法
定制gradle插件,编译期动态替换
总结
卡顿监控重要的一环,全面性保障
TraceView适合线下,可以监控系统Msg
动态替换适合线上,只有应用自身的Msg
技巧总结
实践经验
耗时操作:异步、延迟
布局优化:异步Inflate、X2C、重绘解决
内存:降低内存占用,减少GC时间
工具建设
系统工具认识、使用
SysTrace
TraceView
StrictMode
自动化监控及优化
APM,ANR-WatchDog
高频采集,找出重复率高得堆栈
卡顿监控工具
单点问题:AOP、Hook
盲区监控:gradle编译器替换
卡顿监控指标
卡顿率、ANR率、界面秒开率
交互时间、生命周期时间
上报环境、场景信息