Android性能优化学习笔记
参考
优化类型
- App启动优化
- 布局优化
- 响应优化
- 内存优化
- 电池使用优化
- 网络优化
工具
性能分析工具官方
名称 | 作用 | 说明 | 参考 |
---|---|---|---|
StrictMode | 主要用来做主线程优化分析 | 一般用来检测主线程中的耗 时操作和阻塞.结果在Log console输出一些警告 | 官方文档 |
Systrace | 分析UI的绘制时间, 发现耗时操作, 结合Hierarchy Viewer来提升UI性能 | Systrace是一个收集和检测时间信息的工具, 它能显示CPU和时间被消耗在哪儿了, 每个进程和线程都在其CPU时间片内做了什么事儿. 而且会指示哪个地方出了问题, 以及给出Fix建议. | 文档 文档 文档 |
Hierarchy Viewer | 用来做View层级分析, 可以分析出View Tree中的性能阻塞点, 以便对症下药, 提升布局性能. | Hierarchy Viewer需要Root的机器(产品机没有开启ViewServer)才可以执行.可以使用第三方的开源的ViewServer来协助我们在未Root的机器上使用Hierarchy Viewer分析. | 文档 文档 文档 文档 |
TraceView | 分析方法调用栈以及其执行时间, 优化方法执行. | 一个图形化的工具, 用来展示和分析方法的执行时间. | 文档 文档 |
Memory Monitor | 用来做内存分析, 内存泄露排查的不二之选. 可以结合heap viewer, allocation tracker来分析. | 内存使用检测器, 可以实时检测当前Application的内存使用和释放等信息, 并以图形化界面展示. | 文档 文档 文档 |
Other Monitor | 分别用来跟踪监测CPU,GPU和Network的使用极其变化, 可以作为网络优化, 流量优化和渲染优化等的一个指导 | Android Studio的Monitor还提供了其他三个Motinor --- CPU, GPU, Network. | CPU GPU Network |
- 绿色, 表示该View的此项性能比该View Tree中超过50%的View都要快.
- 黄色, 表示该View的此项性能比该View Tree中超过50%的View都要慢.
- 红色, 表示该View的此项性能是View Tree中最慢的.
第三方
名称 | 作用 | 说明 | 文档 |
---|---|---|---|
Historian | 用来做电量使用分析. | Google出品, 通过Android系统的bugreport文件来做电量使用分析的工具. | Github |
Emmagee | 比官方工具更适合国人使用来做App的整体性能分析. | 针对Android App的CPU, 内存, 网络, 电量等多项综合的测试分析. | Github |
leakcanary | 集成到App中, 用来做内存问题预防最好不过了. | 类似与App探针的内存泄露监测工具. | Github |
AndroidDevMetrics | 如果你的应用使用的Dagger2, 这个就比较必要了. | 一个library, 用来检测Activity生命周期执行性能, Dagger2注入性能以及帧率性能的工具. | Github |
APP启动优化
主要方面
- Application的OnCreate
- 首屏页的渲染
APP启动方式
- 冷启动 : 系统中不存在该App进程, 需要创建APP进程 加载资源 启动mainThread 初始化首屏页
- 热启动 : 系统中存在该App进程, 系统将后台进程切换到前台进程
Application的OnCreate
因为Application的OnCreate一般会初始化大量的集成SDK,此时需要耗费大量CPU事件.
解决方法
启动一个主进程的Service
帮忙初始化SDK,推荐使用IntentService
首屏页的渲染
首屏页作为,APP启动的第一个页面.在应用切换过程中,默认出现白屏(取决于windowBackground
属性).
解决方法
- 首屏页的UI性能需要优化,并且不能是复杂的布局.
- 首屏页设置一个非透明的背景,作为UI启动页
使用TraceView
DDMS启动
DDMS启动代码打桩启动
// 在自己想要开始调试的地方start
Debug.startMethodTracing("filename");
// 在合适的地方stop
Debug.stopMethodTracing();
filename
是dump到内存的数据文件,一般在sdcard的根目录,如果找不到可以使用find / -name filename
查找
把文件拉倒本地,就可以用DDMS打开了
指标说明
-
Incl(Inclusive) Cpu Time
: 方法本身和其调用的所有子方法占用CPU时间 -
Excl(Exclusive) Cpu Time
: 方法本身占用CPU时间 -
Incl Real Time
: 方法(包含子方法)开始到结束用时 -
Excl Real Time
: 方法本身开始到结束用时 -
Call + Recursion Calls/Total
: 方法被调用次数 + 方法被递归调用次数 -
Cpu Time/Call
: 方法调用一次占用CPU时间 -
Real Time/Call
: 方法调用一次实际执行时间
CPU Time
方法实际执行时间(不包括io等待时间)
Real Time
方法开始结束时间差(包括等待时间)
一般来说, 我们使用Real Time/Call排序来找出耗时多的方法
布局优化
Hierarchy Viewer
Hierarchy Viewer
只能在root
过的机器上使用,因为需要View Server
.
解决方案是项目中集成ViewServer
启动
打开HV界面
主页面-
Window
: 显示当前连接的设备和供分析的界面. 可手动选择. -
Tree View
: 树状图的形式展示该Activity中的View层级结构. 可以放大缩小, 每个节点代表一个View, 点击可以弹出其属性, 当前值, 并且在LayoutView中会显示其在界面中相应位置.Tree View是我们主要要分析的视图. -
Tree Overview
: Tree View的概览图. 有一个选择框, 可以拖动选择查看. 选中的部分会在Tree View中显示. -
Layout View
: 匹配手机屏幕的视图, 按照View的实际显示位置展示出来的框图.
参数解读
参数解读- 绿色 : 表示该View的此项性能比该View Tree中超过50%的View都要快.
- 黄色 : 表示该View的此项性能比该View Tree中超过50%的View都要慢.
- 红色 : 表示该View的此项性能是View Tree中最慢的.
如果你的界面的Tree View中红点较多, 那就需要注意了. 一般来说:
- Measure红点, 可能是布局中嵌套RelativeLayout, 或是嵌套LinearLayout都使用了weight属性.
- Layout红点, 可能是布局层级太深.
- Draw红点, 可能是自定义View的绘制有问题, 复杂计算等.
Lint tool
启动
启动分析
分析 分析布局优化
尽量减少布局层级和复杂度
-
尽量不要嵌套使用RelativeLayout.
-
尽量不要在嵌套的LinearLayout中都使用weight属性.
-
Layout的选择, 以尽量减少View树的层级为主.
-
去除不必要的父布局.
-
善用TextView的Drawable减少布局层级
-
如果H Viewer查看层级超过5层, 你就需要考虑优化下布局了
善用Tag
-
<include>
: 使用include来重用布局 -
<merge>
: 解决布局冗余问题 -
<ViewStub>
: 不必要的布局延迟加载
ANR问题
原因
- 5s内无法响应用户输入事件(例如键盘输入, 触摸屏幕等).
- BroadcastReceiver在10s内无法结束.
解决方法
不能在主线程(UI线程)里面做频繁操作
分析
ANR产生时会把日志写到/data/anr/traces.txt
常见原因
-
普通阻塞导致的ANR : 开辟单独的子线程来处理耗时阻塞事务
-
CPU满负荷 : I/O阻塞一般来说就是文件读写或数据库操作执行在主线程了, 也可以通过开辟子线程的方式异步执行
-
内存原因 : 增大VM内存, 使用largeHeap属性, 排查内存泄露
执行在主线程的
-
Activity的所有生命周期回调都是执行在主线程的.
-
Service默认是执行在主线程的.
-
BroadcastReceiver的onReceive回调是执行在主线程的.
-
没有使用子线程的looper的Handler的handleMessage, post(Runnable)是执行在主线程的.
-
AsyncTask的回调中除了doInBackground, 其他都是执行在主线程的.
-
View的post(Runnable)是执行在主线程的.
内存优化
Android虚拟机
- Dalvik
- ART
ART相比Dalvik的关键提升:
-
引入AOT(ahead-of-time)预编译技术
-
GC效率
- 由原来的两次GC暂停减少为一次.
- 以较少的GC时间回收最近分配的, 短命的对象.
- 提升GC工程学, 使并发GC更及时.
- 压缩GC, 以减少后台内存使用和内存碎片.
-
开发和调试
- 支持内存/方法执行的采样分析
- 支持更多的调试技.
- 在Crash report中提供更多信息
Android内存管理
APP的内存分配和回收
-
HeapSize
: 被限制的虚拟空间大小 -
Proportional Set Size (PSS)
: APP应用运行占的内存大小
APP内存限制
-
dalvik.vm.heapstartsize
: App启动后, 系统分配给它的Heap初始大小. 随着App使用可增加. -
dalvik.vm.heapgrowthlimit
: 默认情况下, App可使用的Heap的最大值, 超过这个值就会产生OOM. -
dalvik.vm.heapsize
: 如果App的manifest文件中配置了largeHeap属性, 如下.则App可使用的Heap的最大值为此项设定值 -
dalvik.vm.heaptargetutilization
: 当前理想的堆内存利用率. GC后, Dalvik的Heap内存会进行相应的调整, 调整到当前存活的对象的大小和 / Heap大小 接近这个选项的值, 即这里的0.75. 注意, 这只是一个参考值. -
dalvik.vm.heapminfree
: 单次Heap内存调整的最小值. -
dalvik.vm.heapmaxfree
: 单次Heap内存调整的最大值.
获取方法
cat /system/build.prop
dalvik.vm.heapstartsize=8m
dalvik.vm.heapgrowthlimit=192m
dalvik.vm.heapsize=512m
dalvik.vm.heaptargetutilization=0.75
dalvik.vm.heapminfree=2m
dalvik.vm.heapmaxfree=8m
adb shell getprop dalvik.vm.heapsize
Android进程级别
根据进程的优先级不同而进行回收, 重要程度由高到低:
进程类型 | 说明 |
---|---|
前台进程 | 用户当前操作所必需的进程. |
可见进程 | 没有任何前台组件, 但仍会影响用户在屏幕上所见内容的进程 |
服务进程 | 正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程 |
后台进程 | 包含目前对用户不可见的 Activity 的进程(已调用 Activity 的 onStop() 方法)。这些进程对用户体验没有直接影响 |
空进程 | 不含任何活动应用组件的进程。保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间。 |