Android卡顿优化思路

Posted 嘴巴吃糖了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android卡顿优化思路相关的知识,希望对你有一定的参考价值。

卡顿优化思路

  • 卡顿原理分析
  • 卡顿流程flow
  • 卡顿概貌分析
  • 卡顿实际数据收集
  • 卡顿优化细节

卡顿原因

屏幕刷新频率高于帧率,帧率低于30

每帧执行流程

Choreographer中维护着四个队列callbacks

  • 输入事件队列
  • 动画队列
  • 绘制队列
  • app添加的frameCallback队列

vysnc信号由SurfaceFlinger中创建HWC触发,通过bitTube技术发送到目标进程,目标进程vsync信号到来时,执行Choreographer中的onVsync回调,最终触发doFrame顺序执行这四条队列中的消息。

bitTube

在linux/unix中,bitTube技术成为socketPair,它通过dup技术复制socket的句柄,传递到目标进程,开启socket的全双工通信。

句柄

在内核中,每一个进程都有一个私有的“打开文件表”,这个表是一个指针数组,每一个元素都指向一个内核的打开文件对象。而fd,就是这个表的下标。当用户打开一个文件时,内核会在内部生成一个打开文件对象,并在这个表里找到一个空项,让这一项指向生成的打开文件对象,并返回这一项的下标作为fd.

ui优化

  • 多余Bg移除
  • ui重叠区域优化 cancas.clipRect
  • 减少ui层级
  • 耗时方法分析与优化
  • 多样式布局采用单一rv处理

webview优化

webview的加载流程


webiew初始化

  • 目的是初始化并启动浏览器内核。
  • 提前初始化webview并隐藏 优化126ms

webview 单独进程

  • 单独进程 activity配置
  • 单独进程的交互 webview.addjavascriptInterface(),webview.evalute()

安全性

  • addJavaScriptInterface添加的java对象的方法,需要添加@addJavascriptInterface注解,避免xss攻击

卡顿收集策略

开发卡顿检测StrictMode

private void initStrictMode() 
    if (isDebug()) 
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectCustomSlowCalls() //API等级11,使用StrictMode.noteSlowCode
                .detectDiskReads()
                .detectDiskWrites()
                .detectNetwork() // or .detectAll() for all detectable problems
                .penaltyDialog() //弹出违规提示对话框
                .penaltyLog() //在Logcat 中打印违规异常信息
                .penaltyFlashScreen() //API等级11
                .build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectLeakedSqlLiteObjects()
                .detectLeakedClosableObjects() //API等级11
                .penaltyLog()
                .penaltyDeath()
                .build());
    

线下卡顿检测

  • adb shell dumpsys gfxinfo [packagename]
Applications Graphics Acceleration Info:
Uptime: 205237819 Realtime: 436545102

** Graphics info for pid 5842 [xxxx] **

Stats since: 198741999784549ns
Total frames rendered: 653
Janky frames: 157 (24.04%)
50th percentile: 9ms
90th percentile: 34ms
95th percentile: 53ms
99th percentile: 200ms
Number Missed Vsync: 46
Number High input latency: 268
Number Slow UI thread: 76
Number Slow bitmap uploads: 3
Number Slow issue draw commands: 8
Number Frame deadline missed: 92
  • 通过gpu绘制条形柱分析

条形柱共分为8种颜色,绿色和蓝色部分是异步应用能够优化的部分。包括其他处理 - 输入 - 动画 - travel

BlockCanary检测卡顿

在ActivityThread.main中的Looper大循环中,Looper.looponce会不断从消息队列中取出消息派发出去,并在前后通过logging打印了两个日志,我们通过设置自定义的logger,在两部分日志的时间差与30ms做对比,如果超过30ms,认为是卡顿。

logging.println(">>>>> Dispatching to " + msg.target + " "
                    + msg.callback + ": " + msg.what);
msg.target.dispatchMessage(msg);
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);

卡顿分析信息收集

  • Debug.startMethodTracing 收集具体的卡顿方法
  • 查看trace文件 根据bottomup分析具体的耗时方法
  • 火焰图,横轴是调用方法耗时,纵轴是调用深度
  • 调用图,调用链以及方法耗时

线上卡顿分析与收集

在ActivityThread.main中的Looper大循环中,Looper.looponce会不断从消息队列中取出消息派发出去,并在前后通过logging打印了两个日志,我们通过设置自定义的logger,在两部分日志的时间差与30ms做对比,如果超过30ms,认为是卡顿。将主线程堆栈信息写入到缓存文件并异步发送到日志后台。

常见的卡顿问题

sharepreference

  • 首次读取写入会loadxml到内存
  • sp文件修改是全量读写的
  • commit异步写入,通过CountdownLatch阻塞等待结果
  • apply延迟100ms写入,无返回结果
  • 主线程ANR,sp的修改会先体现在内存中,然后往QueueWorker中加入磁盘异步写数据的任务,但是会在Activity.onResume以及Service.onstartCommand等方法中增加waitToFinish等待磁盘写入完成的代码。
  • 解决方案使用MMKV
  • 尽量拆分小的xml

主线程操作文件

主线程网络操作

以上是关于Android卡顿优化思路的主要内容,如果未能解决你的问题,请参考以下文章

吹爆系列:深入实战Android卡顿优化

Android 性能优化--卡顿优化

Android 性能优化--卡顿优化

Android 性能优化--卡顿优化

Android 性能优化--卡顿优化

Android卡顿优化分析