这是我参与「第四届青训营」笔记创作活动的第9天
课程主要内容
- 为什么做性能优化?
- 性能优化是什么?
- 最佳性能工具选型
- 如何做性能优化?
3. 最佳工具选型
工欲善其事,必先利其器
性能监控价值
- 监控和优化相生相伴
- 监控有攻也有防
- 攻是为了发现现有问题,指导优化方向
- 防是为了发现劣化问题,及时止损
- 线上监控发现问题并聚合排序,线下监控作为线上辅助,并发版前置发现问题
Gpu呈现模式
快速流畅性找出问题
- 原理: 系统通过记录每一帧的相关数据,然后通过图形的形式呈现
- 优点: 无需二次开发,简单易用
- 缺点: 并不完全准确,且无法明确指出造成卡顿问题的具体原因
Layertool
快速找出布局问题
抖音自研工具,快速识别图层及过度绘制、绘制区域过大等问题,提升整体渲染效率
- 原理: 通过遍历ViewTree信息,输出View层级关系
- 优点: 清楚明了,可以宏观感知ViewTree现状,也可以定制,帮助分析overdraw
- 缺点: 还不能够清楚明确的分析出UI的性能瓶颈
CPU Profiler
- 原理: 基于JVMTI
- 优点: 完整的方法调用栈输出、支持Java、C、C++方法耗时检测、上手简单
- 缺点: 性能损耗太大
TraceView
- Instrument
- 虚拟监听函数入口回调,Enter/Exit/Unwind
- 耗时点:读时间、写数据到buffer、加锁等指令
- Sample
- 通过定时抓取多次堆栈diff,近似确定函数的进入和退出时间
- 耗时点:堆栈diff、同Instrument
- 间隔抓取堆栈的时间越长性能损耗越少,而越会导致短函数检测不到
Systrace
- ftrace: debugfs采集和读取trace数据,记录trace events
- atrace:用户侧的trace跟踪,聚合所有的trace event
- 系统级的Trace数据:锁监控等
深入性能归因:初阶CPU profiler 中阶TraceView 高阶Systrace
btrace (aka rhea)-进阶
抖音大杀器
- rhea-systrace:全函数插桩,自动生成Trace代码,对层数做限制,性能损耗50%
- rhea-mtrace:全函数插桩,抛弃systrace,自己统计函数耗时,最后数据展现同systrace
- rhea-atrace:优化systrace性能,聚合更多性能数据:类加载、Lock、IO等
Battery Historian
查出功耗问题
4. 如何做性能优化?
1. 现状分析
耗时成因
- CPU Time
循环,反射,序列化/反序列化,类解析
- IO Wait
IO操作,等待lO返回结果
- IPC
Binder调用耗时
- Lock Wait
主线程是等锁状态,等待其他线程或者自己超时唤醒
- CPU Schedule
主线程是可执行状态,但是获取不到CPU时间片
运行环境归因
- 根据耗时成因归类
- 根据运行所在线程环境采用不同的策略
抖音启动耗时归因
- Cold Start
- Create process
- ContentProvider init
- Application#Create
- Aim for <3 seconds
- Warm Start
- Activity#Create
- Inflate view hierarchy
- Aim for <1 seconds
- Hot Start
- Activity#onStart()
渲染分析
渲染瓶颈
- 渲染耗时
- inflater
- init
- bind
- measure/layout/draw
- overdraw
- 渲染频率
- AnimatorFPS
- Vsync Leak
- requestlayout、loop
从任务角度和耗时角度拆解一帧的耗时
洞察程序内部的瓶颈,层层剥离,最终才能发现问题根源
2. 经典案例
- 入门:一个view的成长史
- 初阶:View的构建优化
- 初阶:如何快速的填充View
- 初阶:View之间的组合优化
- 高阶:如何解决构建、填充、组合带来的主线程流畅问题——>异步,多核并发
后记
通过这节课程,了解了最佳性能工具选型以及做性能优化的现状分析,学习了性能监控价值等内容,对性能优化有了更深入的了解。