1. 前言

android开发中卡顿问题一直是个比较棘手又重要的问题,严重影响用户体验。刚好有段时间,负责APP的性能调优工作,总结了遇到的一些卡顿问题,分析思路及常见问题。最终使得卡顿问题,明显优化,在低端手机上,效果尤为明显,记录下

1.1 绘制基础:渲染UI的两个控件: CPU 、 GPU 。

CPU 负责 Measure 、 layout 、 Record 、 Execute 的计算操作。

android 视频 掉帧 分析 安卓掉帧优化_android 视频 掉帧 分析


GPU 负责栅格化(Rasterization):

将 Button 、 Shape 、 Path 、 Bitmap 等资源组件拆分到不同的像素上显示

android 视频 掉帧 分析 安卓掉帧优化_分析卡顿_02

1.2 掉帧原理

android 视频 掉帧 分析 安卓掉帧优化_android 性能优化_03


android 视频 掉帧 分析 安卓掉帧优化_android 视频 掉帧 分析_04

  • Android系统每隔16ms会发出VSYNC信号,当 VSync 同步信号发出时,如果画面(view)准备好了,view绘制就会很流畅(60fps)。
  • Vsync发出时, GPU/CPU 正在生产帧数据,从 Frame Buffer 中取出的是“旧”数据,而非正在产生的“新”数据,即两个刷新周期显示的是同一帧数据。这时我们称发生了“掉帧”(Dropped Frame,Skipped Frame,Jank)。

2. 流畅度基本指标

Android系统要求每一帧都要在 16ms内绘制完成,这个速度允许系统在动画和输入事件的过程中以约60帧每秒(1秒 / 0.016秒每帧 = 62.5帧/秒)的平滑帧率来渲染 。目前显示性能优化的极限是 60 fps。

为什么是60fps?
绝大多数Android设备的刷新频率是60hz, GPU渲染图像的频率则各自不同,为了避免屏幕撕裂现象,引入专门的V-Sync 技术。
V-Sync控制GPU载入新帧前,等待屏幕绘制完前一帧,通过同步渲染/刷新时间,控制GPU渲染速度在60fps以内以匹配显示器刷新频率,意味着帧率的极限是60fps.

3. 导致卡顿的因素

3.1 硬件因素

CPU
  RAM
  ROM
  HeapSize
  SDK Version

3.2.软件因素

UI渲染相关
UI线程操作相关

4. 常见分析方法

1. Systrace
2. TraceView
3. Android Device Monitor
4. GPU渲染模式
5. 严格模式(基线已有引入,效果不明显)
6. BlockCanary

4.1 常见分析方法 – Systrace

以Linux Kernel的ftrace为基础,内部采用systrace.py统计数据。通常截取一小段时间,例如2-5s,针对性分析。主要cpu及UI Thread渲染情况,GC回收情况

重点关注卡顿帧(红色F)

android 视频 掉帧 分析 安卓掉帧优化_工作总结_05

4.2 常见分析方法 – TraceView

跟踪构造视图,主要是从线程执行时间,方法调用情况(递归次数等),CPU占用情况维度分析

重点关注占用cpu最多,方法调用或者递归调用较大的thread

在这里插入图片描述

android 视频 掉帧 分析 安卓掉帧优化_android 性能优化_06

4.3 常见分析方法 – Android Profiler

CPU,Memory,NetWork 维度分析

重点分析内存抖动,及高cpu占用时的调用栈

android 视频 掉帧 分析 安卓掉帧优化_工作总结_07

5. 目前发现的常见卡顿点

UI渲染相关
布局嵌套过深
measure,inflate 过程复杂
UI线程操作相关
主线程执行IO操作
并发线程数过高
主线程执行耗时操作
锁竞争
主线程操作数据库

5.1 常见卡顿点 --001

Layout Inflate 卡顿 – 降低布局复杂度

android 视频 掉帧 分析 安卓掉帧优化_卡顿_08

5.2 常见卡顿点 --002

拷贝BitMap 跑在主线程里

android 视频 掉帧 分析 安卓掉帧优化_android 视频 掉帧 分析_09

5.3 常见卡顿点 --003

JSon 解析 – new JSONObject(jsonStr)

android 视频 掉帧 分析 安卓掉帧优化_卡顿_10

5.4 常见卡顿点 --004

JSon 解析 – Gson.fromJosn()

android 视频 掉帧 分析 安卓掉帧优化_分析卡顿_11

5.5 常见卡顿点 --005

耗时操作,读取运行时参数

android 视频 掉帧 分析 安卓掉帧优化_分析卡顿_12

5.6 常见卡顿点 --006

竞争锁,人为阻塞

个别地方人为设置了阻塞,例如满足特定条件才会解除阻塞,此类型应特别慎重,我们曾经有个业务首刷广告处,因此导致页面卡顿严重

android 视频 掉帧 分析 安卓掉帧优化_分析卡顿_13


android 视频 掉帧 分析 安卓掉帧优化_分析卡顿_14

5.7 隐蔽卡顿点 --007

并发IO操作线程过多

严重卡顿导致ANR,可通过分析anr/traces.txt 查明原因。如我们有次发布卡顿严重的原因是并发下载不加限制,导致IO过频

android 视频 掉帧 分析 安卓掉帧优化_分析卡顿_15


android 视频 掉帧 分析 安卓掉帧优化_分析卡顿_16

5.5 隐蔽卡顿点 --008

内存频繁触发GC过多(同一帧中频繁创建内存,内存优化参见LeakCanary)

android 视频 掉帧 分析 安卓掉帧优化_工作总结_17

6. 目前针对低端机卡顿所做优化

界定了低端机性能指标,统一控制处理
布局层级降低1层
归纳分拆了非核心后台进程,关闭了部分非核心业务
归纳分拆了后台自启的下载任务,关闭了大部分自启任务
修复了大部分平时开发中发现的常见卡顿问题

7. 其他可能的卡顿原因(持续补充中…)

IO操作出现在主线程中
创建太多子线程,且不区分优先级,必要时使用线程池,或交由调度器处理。
主线程操作数据库
复杂运算交还云端,确需本地进行,可通过RenderThread( Android L)放到GPU中调用
UI刷新时,尽量避免全局刷新,如RecyclerView:notifyDataSetChanged
布局复用少(Merge标签),过多使用weight、 stretchColumns、 shrinkColumns等可能导致重绘的标签过多