Android 应用性能优化(4)---Android App性能评测分析-启动时间篇
Android App性能评测分析-启动时间篇
1、前言
随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,性能问题从应用的启动优化开始,下面会根据实际app性能测试案例,进行app性能评测之启动时间的分析和总结。
2、App启动方式了解
通常来说, 一个App启动也会分如下三中不同的状态:
冷启动
当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动,也就是先实例化Application冷启动的流程即为App启动流程的全过程, 需要创建App进程, 加载相关资源, 启动Main Thread, 初始化首屏Activity等.
在这个过程中, 屏幕会显示一个空白的窗口(颜色基于主题), 直至首屏Activity完全启动.
下图展示了冷启动的时间线:
冷启动流程.png
热启动
当启动应用时,后台已有该应用的进程,这时会从已有的进程来启动Activity(不需要重新创建Application)类同与冷启动, 在这个过程中, 屏幕会显示一个空白的窗口(颜色基于主题), 直至activity渲染完毕.
温启动
介于冷启动和热启动之间, 一般来说在以下两种情况下发生:用户back退出了App, 然后又启动. App进程可能还在运行, 但是activity需要重建.
用户退出App后, 系统可能由于内存原因将App杀死, 进程和activity都需要重启, 但是可以在onCreate中将被动杀死锁保存的状态(saved instance state)恢复.
通过三种启动状态的相关描述, 可以看出我们要做的启动优化其实就是针对冷启动. 热启动和温启动都相对较快.
3、性能评测结果案例分析
3.1 XX银行 APP启动时间评测结果分析
3.1.1 启动时间测试结果
统计的时间为APP的冷启动时间,4G网络情况下,平均冷启动时间为14.1S,平均热启动时间为6.7S,无网络时平均启动时间为5.2S。由于APP的启动时间耗时远远超过行业标准水平3S,当app启动时,任何一个地方有耗时操作都会拖慢我们应用的启动速度,所以针对APP启动时间做了具体分析
3.1.2评测结果分析
首先来看App从点击桌面图标到我们看到App的主界面整个过程中经过了哪些步骤:
启动虚拟机—>启动AMS —>通过Zygote创建ApplicationProcess进程–>Application的构造器方法——>attachBaseContext()——>onCreate()——>Activity的构造方法——>onCreate()——>配置主题中背景等属性——>onStart()——>onResume()——>测量布局绘制显示在界面上。
1)初始化Application
- 【初始化Application】应用程序初始化总共耗费了3.26S,耗时已超过行业APP启动标准基线时间3S。具体看下耗时详情分析:
(1)应用Application.attach的时间较长。应用存在多个dex文件,请控制应用方法数量。
(2)onCreate方法耗时长,主要体现BaseApplication创建上。
长耗时方法排名如下:
1.com.pingan.fstandard.framework.base.BaseApplication.onCreate(BaseApplication.java)
- com.pingan.fstandard.common.c.a(InitManager.java)
- com.pafinancialtech.pafs.kitchendaddy.f.b(PAFFToast.java:83
4.com.pingan.fstandard.HomeApplication.d(HomeApplication.java:51
综上分析,BaseApplication创建上耗费较长时间,需要开发进行更详细的分析优化。另外,初始化Application时,也包含了任意门相关等非核心功能的程序,建议启动时不创建该类程序。
2)初始化Activity
- 【初始化Activity】耗时也过长,耗时约1s左右
主要耗时的地方是在闪屏界面创建oncreate时com.pingan.fstandard.activity.SplashActivity.onCreate,建议开发优化
3)加载请求及响应
首先来一张流程图了解一下我们APP首页加载的一个流程
页面加载流程.png
冷启动资源加载.png
- 【网络请求及响应】总体来看,首页加载耗时占比最多,需要6s左右,对应的网络消耗时间占比45%左右。
根据抓包及代码段分析显示APP启动到首页加载完成是一个预加载和异步加载的过程。
(1) 项目中大部分第三方组件都抢占先机,在Application主线程初始化。这样的初始化方式肯定是过重的,建议考虑异步初始化三方组件,不阻塞主线程;延迟部分三方组件(比如埋点统计、任意门、ImageLoader的初始化)。
(2) 启动到首页加载完成网络请求密集,请求内容丰富,部分资源重复请求。
请求了相关配置信息、启动页广告、个推、磁贴配置信息、商城理财产品列表,运营广告Banner、F后端接口,广告BANNER位、插件信息、任意门、百度地图SDK(talkingdata、灰度升级)等林林总总加起来就有40+个网络请求,加载的数据+广告页一共有1.7M左右,这说明了我们的APP首页设计的内容比较丰富,部分资源重复请求,部分内容需要调外部接口,所以耗时比较长,这是产品设计问题、信息未做缓存处理和部分外部关联方接口响应慢的原因导致,建议优化。
(3)非核心功能资源过早请求加载
另外其中类似百度地图SDK、任意门、微信sdk相关插件只有在生活页\分享时使用到的非主要业务功能启动时也加载出来了,建议开发同学和产品同学调整APP启动时网络请求的加载策略,非核心/主要/高PV的功能相关的API,SDK、插件等没有必要在启动时做加载缓存,这是非常耗时且得不偿失的。
3.1.3启动时间优化建议
(1)应用Application.attach的时间较长。应用存在多个dex文件,请控制应用方法数量。
(2)onCreate方法耗时长,主要体现BaseApplication创建上,需要开发进行更详细的分析优化,建议考虑异步初始化三方组件,不阻塞主线程;延迟或者和产品一起梳理需要的去除的部分三方组件(比如统计、任意门、ImageLoader的初始化)。
(3)com.pingan.fstandard.activity.MainActivity存在过度绘制导致卡顿,首页UI布局层次过多,建议开发进一步分析优化
(4)建议产品调整优化app启动时网络请求的加载策略,非核心/主要/高PV的功能相关的API,SDK、插件等没有必要在启动时做加载缓存
(5)部分资源重复请求,建议信息缓存,常用信息只在第一次获取,之后从缓存中取
(6)建议开发梳理无用但被执行的老代码,去掉无用但被执行的老代码
综上,建议开发童鞋尽快投入做APP启动时性能改善和优化,以提升行业相比竞品的竞争力。
4、App端启动耗时排查方法及思路
4.1 排查方法:使用Traceview分析
TraceView 是 Android SDK 中内置的1个工具,它可以加载 trace 文件,用图形的情势展现代码的履行时间、次数及调用栈,便于我们分析。
(1)使用Android Studio工具DDMS
生成Traceview 进行分析查看具体Trace期间各方法调用关系,调用次数以及耗时比例
ddms.png
(2)使用代码生成 trace 文件
Debug.startMethodTracing("shixintrace"); //开始 trace,保存文件到 "/sdcard/shixintrace.trace"// ...Debug.stopMethodTracing(); //结束
代码很简单,当你调用开始代码的时候,系统会生产 trace 文件,并且产生追踪数据,当你调用结束代码时,会将追踪数据写入到 trace 文件中。
下1步使用 adb 命令将 trace 文件导出到电脑:
adb pull /sdcard/shixintrace.trace /tmp
使用代码生成 trace 方式的好处是容易控制追踪的开始和结束,缺点就是步骤略微多了一点。
(3)直接使用android studio生成trace文件
Android Studio 内置的 Android Monitor 可以很方便的生成 trace 文件到电脑。
注意:此方法仅仅适用于下拉代码到本地生成DEBUG测试包到手机进行调试
monitor1.png
monitor2.png
分析指标:
不应在Application以及Activity的生命周期回调中做任何费时操作,具体指标大概是你在onCreate,onResume,onStart等回调中所花费的总时间最好不要超过400ms,否则用户在桌面点击你的应用图标后,将感觉到明显的卡顿。
4.2 开启严苛模式(StrictMode)
检查是否有主线程做了耗时操作: 开启 严苛模式(StrictMode)
(1)StrictMode可以用于捕捉发生在应用程序 主线程中耗时的磁盘、网络访问或函数调用,使主线程处理UI和动画在磁盘读写和网络操作时变得更平滑,避免主线程被阻塞,导致ANR窗口的发生。
下面是启用StrictMode的实例,可以在Application的OnCreate中添加,这样就能在程序启动的最初一刻进行监控了。
private void setStrictMode() {if (Integer.valueOf(Build.VERSION.SDK) > 3) {Log.d(LOG_TAG, "Enabling StrictMode policy over Sample application");StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll() // 这里可以替换为.detectDiskReads().detectDiskWrites().detectNetwork()。// detectAll() 包括了磁盘读写和网络I/O.penaltyLog() //打印logcat,当然也可以定位到dropbox,通过文件保存相应的log.penaltyDeath().build());StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());}}
(2)除了通过日志查看之外,我们也可以在开发者选项中开启严格模式,开启之后,如果主线程中有执行时间长的操作,屏幕则会闪烁,这是一个更加直接的方法。
4.3、通过抓包工具分析
可以通过抓包工具Charels、Fiddler等查看网络请求加载了哪些资源,加载资源的顺序、哪些资源重复加载、信息是否缓存
4.4、查看Logcat
通过adb输出log信息,过滤日志查看APP启动时每个方法的大致耗时。
4.5、启动时间排查思路
对于App来说, 我们可以控制的启动时间线的点无外乎:
Application的onCreate
首屏Activity的渲染
而我们现在的App动不动集成了很多第三方服务, 启动时需要检查广告, 注册状态等等一系列接口都是在Application的onCreate或是首屏的onCreate中做的.
5、启动时间耗时常见原因及优化建议
5.1、 常见主要问题(持续补充ing)
- 部分数据库及IO的操作发生在首屏Activity主线程;
- Application中创建了线程池;
- 启动时做密集沉重的初始化(Heavy app initialization);
- Multidex的使用,也是拖慢启动速度的元凶;
- UI存在过度绘制;
- 首屏Activity网络请求密集;
- 非核心功能资源过早请求加载
- 工作线程使用未设置优先级;
- 信息未缓存,重复获取同样信息;
- 流程问题:例如闪屏图每次下载,当次使用;
- 执行无用老代码;
- 执行开发阶段使用的代码;
- 执行重复逻辑;
- 调用三方SDK里或者Demo里的多余代码;
5.2、建议:
- 去掉无用但被执行的老代码;
- 去掉开发阶段使用但线上被执行的代码;
- 去掉重复逻辑执行代码;
- UI渲染优化,去除重复绘制,减少UI重复绘制时间
- 去掉调用三方SDK里或者Demo里的多余代码;
- 信息缓存,常用信息只在第一次获取,之后从缓存中取;
- 项目是多进程架构,只在主进程执行Application的onCreate();
- 根据优先级的划分,一些初始化工作能否将任务优先级划分成3个等级,任务优先级为2,3的,通过懒加载的方式在首页渲染完成后进行加载
- 避免I/O操作、反序列化、网络操作、布局嵌套等。
Android 应用性能优化(4)---Android App性能评测分析-启动时间篇相关推荐
- Android性能优化(一):APP启动优化
Android性能优化(一):APP启动优化 性能优化系列文章: Android性能优化(一):APP启动优化 Android性能优化(二):UI布局优化 Android性能优化(三):响应优化 An ...
- Android 系统性能优化(42)---Android代码内存优化建议-Android资源篇
Android代码内存优化建议-Android资源篇 这篇文章主要介绍在实际Android应用程序的开发中,容易导致内存泄露的一些情况.开发人员如果在进行代码编写之前就有内存泄露方面的基础知识,那么写 ...
- 【Android 安装包优化】Android 中使用 7zr 可执行程序 解压缩文件
文章目录 一.Android 中使用 7zr 可执行程序 解压缩文件 二.完整代码示例 三.参考资料 一.Android 中使用 7zr 可执行程序 解压缩文件 在上一篇博客 [Android 安装包 ...
- 【Android 安装包优化】Android 中使用 7zr 可执行程序 压缩文件
文章目录 一.Android 中使用 7zr 可执行程序压缩文件 二.完整代码示例 三.参考资料 一.Android 中使用 7zr 可执行程序压缩文件 在上一篇博客 [Android 安装包优化]A ...
- 【Android 安装包优化】Android 中使用 SVG 图片 ( Android 5.0 以下的矢量图方案 | 矢量图生成为 PNG 图片 )
文章目录 一.Android 5.0 以下的矢量图方案 二.矢量图生成为 PNG 图片 三.完整的 build.gradle 构建脚本 四.编译效果 五.参考资料 一.Android 5.0 以下的矢 ...
- 前端性能优化(一)性能优化的指标和工具
前端性能优化(一)性能优化的指标和工具 一.性能指标 1. F12 network进行调试,我们以淘宝为例 2. 此外还有一个瀑布流的概念 waterfall 3.蓝线和红线 4.保存当前网页指标,方 ...
- 【Linux 性能优化系列】Linux 性能优化 -- CPU 性能篇(三) Linux 软中断
[Linux 性能优化系列]Linux 性能优化 -- CPU 性能篇(三) Linux 软中断 [1]相关概念 [1.1]中断 中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力:为了减少 ...
- 【Linux 性能优化系列】Linux 性能优化 -- CPU 性能篇(一) 平均负载、上下文切换、CPU 使用率
[Linux 性能优化系列]Linux 性能优化 -- CPU 性能篇(一) 平均负载.上下文切换.CPU 使用率 [1]相关概念 [1.1]平均负载 平均负载是指单位时间内,系统处于可运行状态和不可 ...
- 性能优化:Android App启动速度优化
一.App启动分类 1.冷启动 Cold start 在启动应用前,系统还没有App的任何进程.比如设备开机后应用的第一次启动,系统杀掉应用进程 (如:系统内存吃紧引发的 kill 和 用户主动产生的 ...
最新文章
- gitter 卸载_最佳Gitter频道:VR和AR
- git branch
- linux下查看已经安装的jdk 并卸载jdk
- MySQL 笔记5 -- 多表查询
- java面试mysql的引擎_面试官:你用过mysql哪些存储引擎,请分别展开介绍一下
- IBastis配置实例
- vue 动态数据请求
- win10环境下VTK7.1的编译和Qt调用VTK的详细教程二(VS2013编译支持Qt的VTK库)
- Facebook已经过时,蜂巢新网络崛起
- 云计算教程学习入门视频:云计算的模型都有哪些
- web前端基础(08html5新标签)
- Java中抽象类和接口的区别(来源一)
- Windows域控设置 AD域策略屏蔽端口 禁用端口【全域策略生效】
- Kalman filter—直观理解
- 冒险岛如何修改服务器wz,冒险岛怎么WZ修改攻击力说好了加100分
- Dorado7 首页菜单CSS调整
- 【基于51单片机驱动ST7789VW的TFT显示屏240x240
- 网络架构采用 bs/cs 混搭模式_最高处|SM一姐出道20年充满偶像气质天生音乐才能还有最高级的混搭_休闲...
- 每次打开Photoshop显示失败恢复文件清理方法
- 拨开迷雾选型数据中台,兼谈这些供应商的商业模式
热门文章
- 由PPPOE看Linux网络协议栈的实现
- oracle ebs 采购订单 为员工分配职务,oracle—EBS-采购功能点操作手册
- linux默认安装数据库密码是多少,Linux服务器上安装MySql数据库(默认安装,密码为空),首次使用需要修改密码(示例代码)...
- php的toast,jQuery 一句代码轻松实现 Toast 的提示框
- 力扣812.最大三角形面积
- 开源框架openresty+nginx 实现web应用防火墙(WAF)
- C# 输入一个整数,求质因数
- 如何快速取消svn的关联
- markdown方式测试图片2
- 实现在Android 多点手势识别