性能优化(四):卡顿优化

504 阅读5分钟

一.卡顿介绍及优化工具选择

背景介绍:
1.很多性能问题不易被发现,但卡顿很容易被直观感受;
2.卡顿问题难以定位排查;
 a.产生原因错综复杂:代码,内存,绘制,IO?
 b.不易复现:当时场景强相关;
工具介绍:
1.CUP Profiler:
 a.图形的形式展示执行时间,调用栈等;
 b.信息全面,包含所有线程;
 c.运行时开销严重,整体都会变慢,可能会带偏优化方向;
 使用方式:
 Debug.startMethodTracing("");
 Debug.stopMethodTracing("");
 生成文件在sd卡:Android/data/packegename/files 直接打开;
2.Systrace:
 a.监控和跟踪Api调用,线程运行情况,生成Html报告;
 b.API18以上使用,推荐TraceCompat;
 优点:轻量级,开销小;直观反映CPU利用率;给出建议;
3.StrictMode
 a.严苛模式,Android提供的一种运行时检测机制;
 b.方便强大,容易被忽视;
 c.包含:线程策略和虚拟机策略检测;
 线程策略:
 1.自定义的耗时调用,detectCustomSlowCalls();
 2.磁盘读取操作,detectDiskReads;
 3.网络操作,detectNetwork;
 虚拟机策略:
 1.Activity泄漏,detectActivityLeaks();
 2.Sqlite对象泄漏,detectLeakedSqlLiteObjects;
 3.检测实例数量,setClassInstanceLimit();

二.自动化卡顿检测方案及优化

为什么需要自动化检测方案?
1.系统工具适合线下针对性分析;
2.线上及测试环节需要自动化检测方案;
方案原理:
1.消息处理机制,一个线程只有一个Looper;
2.mLogging对象在每个message处理前后被调用;
3.主线程发生卡顿,是在dispatchMessage执行耗时操作;
具体实现:
1.Looper.getMainLooper().setMessageLogging();
2.匹配>>>>>Dispatching,阈值时间后执行任务(获取堆栈);
3.匹配<<<<<Finished,任务启动之前取消掉;
AndroidPerformanceMonitor:
1.非侵入式的性能监控组件,通知形式弹出卡顿信息;
2.方便精准,定位到代码的某一行;
缺点:
1.卡顿堆栈可能不准确;
2.和OOM一样,最后的堆栈只是表象,不是真正的问题;
优化:
获取监控周期内的多个堆栈,而不仅是最后一个;
startMonitor-->高频采集堆栈-->endMonitor-->记录多个堆栈-->上报;
高频卡顿上报量太大,服务端有压力,优化处理:
1.分析:一个卡顿下多个堆栈大概率有重复;
2.解决:对一个卡顿下堆栈进行hash排重,找出重复的堆栈;
3.效果:极大的减少展示量,同时更高效找到卡顿堆栈;

三.ANR分析与是实战

1.ANR介绍:
 a.KeyDispatchTimeout,5s;
 b.BroadcastTimeout,前台10s,后天60s;
 c.ServiceTimeout,前台20s,后台200s;
 d.ContentProviderTimeout,10s;
2.ANR执行流程:
 a.发生ANR;
 b.进程接收异常终止信号,开始写入进程ANR信息;
 c.弹出ANR提示框(Rom表现不一);
3.ANR解决套路(线下):
 a.adb pull data/anr/traces.txt 存储路径;
 b.详细分析:CPU,IO,锁
4.线上ANR监控方案
 a.通过FileOberver监控文件变化,注意高版本权限限制;
 b.ANR-WatchDog:非侵入式的ANR监控组件;弥补高版本无权限问题;
实现原理:
start-->post消息改值-->sleep-->检测是否修改-->判断ANR发生;
自身项目中:复写其listener,自己处理堆栈信息,上报服务器;
5.AndroidPerformanceMonitor与ANR-WatchDog区别:
 a.AndroidPerformanceMonitor:监控Msg;
 b.ANR-WatchDog:看最终结果;
 c.前者适合监控卡顿,后者适合补充ANR监控;

四.卡顿单点问题检测方案

背景介绍:
1.自动卡顿检测方案并不够满足所有场景的要求;
2.体系化解决方案务必尽早暴露问题;
3.单点问题:主线程IPC,DB操作;
IPC问题监测:
1.监测指标:
 a.IPC调用类型;
 b.调用耗时,次数;
 c.调用堆栈,发生线程;
常规方案: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;
优雅方案:
1.ARTHook还是AspectJ?
2.ARTHook:可以Hook系统方法;
3.AspectJ:非系统方法;
总结:
1.利用ARTHook完善线下工具;
2.开发阶段Hook相关操作,暴露,分析问题;
3.监控维度:IPC,IO,DB,View绘制;

五.如何实现界面秒开?

1.可把界面秒开当做一个小的启动优化;
2.可借鉴启动优化及布局优化章节;
3.Systrace,优雅异步+优雅延迟初始化;
4.异步Inflate,X2C,绘制优化;
5.提前获取页面数据
Lancet:轻量级Android AOP框架:
1.编译速度快,支持增量编译;
2.API简单,没有任何多余代码插入apk;
@Proxy:通常用于对系统API调用的Hook;
@Insert:常用于操作App与Library的类;
监控维度:
1.总体耗时;
2.生命周期耗时;
3.生命周期间隔耗时;

六.优雅监控耗时盲区

背景:
1.生命周期的间隔;
2.onResume到Feed展示的间隔;
监控难点:
1.只知道盲区时间,不清楚具体在做什么;
2.线上盲区无从排查;
线下方案:TraceView:特别适合一段时间内的盲区监控;线程具体时间做了什么,一目了然;
线上方案思考分析:
1.主线程所有方法是Msg,mLogging?没有Msg具体堆栈;
2.AOP切Handler方法?不清楚准确执行时间;
最终实现:
1.使用统一的Handler:定制具体方法;
2.定制gradle插件,编译期动态替换;

七.卡顿优化技巧总结

1.实践经验
 a.耗时操作:异步,延迟;
 b.布局优化:异步Inflate,X2C,重绘解决;
 c.内存:降低内存占用,减少GC时间;
2.工具建设:系统工具认识及使用
 a.Systrace,TraceView,StrictMode
 b.自动化监控及优化:AndroidPerformanceMonitor,ANR-WatchDog;高频采集,找出重复率高的堆栈;
3.卡顿监控工具:单点问题:AOP,Hook;盲区监控:gradle编译期替换
4.监控指标:a.卡顿率,ANR率,界面秒开率;b.交互时间,生命周期时间;c.上报环境,场景信息;

八.模拟面试

1.你是怎么做卡顿优化的?
 第一阶段:系统工具定位,解决;
 第二阶段:自动化卡顿方案及优化;
 第三阶段:线上监控及线下监测工具建设;
2.怎么自动化的获取卡顿信息?
 思路来自Android消息处理机制,mLogging.pringIn;高频采集,找出重复堆栈;
3.卡顿的一整套解决方案是怎么做的?
 a.线上,线下工具相结合;
 b.特定难题突破:单点问题,盲区监控;
 c.线上监控建设