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)

  1. com.pingan.fstandard.common.c.a(InitManager.java)
  2. 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性能评测分析-启动时间篇相关推荐

  1. Android性能优化(一):APP启动优化

    Android性能优化(一):APP启动优化 性能优化系列文章: Android性能优化(一):APP启动优化 Android性能优化(二):UI布局优化 Android性能优化(三):响应优化 An ...

  2. Android 系统性能优化(42)---Android代码内存优化建议-Android资源篇

    Android代码内存优化建议-Android资源篇 这篇文章主要介绍在实际Android应用程序的开发中,容易导致内存泄露的一些情况.开发人员如果在进行代码编写之前就有内存泄露方面的基础知识,那么写 ...

  3. 【Android 安装包优化】Android 中使用 7zr 可执行程序 解压缩文件

    文章目录 一.Android 中使用 7zr 可执行程序 解压缩文件 二.完整代码示例 三.参考资料 一.Android 中使用 7zr 可执行程序 解压缩文件 在上一篇博客 [Android 安装包 ...

  4. 【Android 安装包优化】Android 中使用 7zr 可执行程序 压缩文件

    文章目录 一.Android 中使用 7zr 可执行程序压缩文件 二.完整代码示例 三.参考资料 一.Android 中使用 7zr 可执行程序压缩文件 在上一篇博客 [Android 安装包优化]A ...

  5. 【Android 安装包优化】Android 中使用 SVG 图片 ( Android 5.0 以下的矢量图方案 | 矢量图生成为 PNG 图片 )

    文章目录 一.Android 5.0 以下的矢量图方案 二.矢量图生成为 PNG 图片 三.完整的 build.gradle 构建脚本 四.编译效果 五.参考资料 一.Android 5.0 以下的矢 ...

  6. 前端性能优化(一)性能优化的指标和工具

    前端性能优化(一)性能优化的指标和工具 一.性能指标 1. F12 network进行调试,我们以淘宝为例 2. 此外还有一个瀑布流的概念 waterfall 3.蓝线和红线 4.保存当前网页指标,方 ...

  7. 【Linux 性能优化系列】Linux 性能优化 -- CPU 性能篇(三) Linux 软中断

    [Linux 性能优化系列]Linux 性能优化 -- CPU 性能篇(三) Linux 软中断 [1]相关概念 [1.1]中断 中断其实是一种异步的事件处理机制,可以提高系统的并发处理能力:为了减少 ...

  8. 【Linux 性能优化系列】Linux 性能优化 -- CPU 性能篇(一) 平均负载、上下文切换、CPU 使用率

    [Linux 性能优化系列]Linux 性能优化 -- CPU 性能篇(一) 平均负载.上下文切换.CPU 使用率 [1]相关概念 [1.1]平均负载 平均负载是指单位时间内,系统处于可运行状态和不可 ...

  9. 性能优化:Android App启动速度优化

    一.App启动分类 1.冷启动 Cold start 在启动应用前,系统还没有App的任何进程.比如设备开机后应用的第一次启动,系统杀掉应用进程 (如:系统内存吃紧引发的 kill 和 用户主动产生的 ...

最新文章

  1. gitter 卸载_最佳Gitter频道:VR和AR
  2. git branch
  3. linux下查看已经安装的jdk 并卸载jdk
  4. MySQL 笔记5 -- 多表查询
  5. java面试mysql的引擎_面试官:你用过mysql哪些存储引擎,请分别展开介绍一下
  6. IBastis配置实例
  7. vue 动态数据请求
  8. win10环境下VTK7.1的编译和Qt调用VTK的详细教程二(VS2013编译支持Qt的VTK库)
  9. Facebook已经过时,蜂巢新网络崛起
  10. 云计算教程学习入门视频:云计算的模型都有哪些
  11. web前端基础(08html5新标签)
  12. Java中抽象类和接口的区别(来源一)
  13. Windows域控设置 AD域策略屏蔽端口 禁用端口【全域策略生效】
  14. Kalman filter—直观理解
  15. 冒险岛如何修改服务器wz,冒险岛怎么WZ修改攻击力说好了加100分
  16. Dorado7 首页菜单CSS调整
  17. 【基于51单片机驱动ST7789VW的TFT显示屏240x240
  18. 网络架构采用 bs/cs 混搭模式_最高处|SM一姐出道20年充满偶像气质天生音乐才能还有最高级的混搭_休闲...
  19. 每次打开Photoshop显示失败恢复文件清理方法
  20. 拨开迷雾选型数据中台,兼谈这些供应商的商业模式

热门文章

  1. 由PPPOE看Linux网络协议栈的实现
  2. oracle ebs 采购订单 为员工分配职务,oracle—EBS-采购功能点操作手册
  3. linux默认安装数据库密码是多少,Linux服务器上安装MySql数据库(默认安装,密码为空),首次使用需要修改密码(示例代码)...
  4. php的toast,jQuery 一句代码轻松实现 Toast 的提示框
  5. 力扣812.最大三角形面积
  6. 开源框架openresty+nginx 实现web应用防火墙(WAF)
  7. C# 输入一个整数,求质因数
  8. 如何快速取消svn的关联
  9. markdown方式测试图片2
  10. 实现在Android 多点手势识别