Android App性能评测分析-启动时间篇

简介: 1、前言随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,性能问题从应用的启动优化开始,下面会根据实际app性能测试案例,进行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操作、反序列化、网络操作、布局嵌套等。

参考文献:
学习地址:
https://www.cnblogs.com/sunzn/p/3192231.html
http://www.wfuyu.com/technology/27625.html
http://blog.csdn.net/qq_16131393/article/details/51172488

目录
相关文章
|
1月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
143 0
安卓项目:app注册/登录界面设计
|
10天前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
2月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
125 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
2月前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
164 2
|
2月前
|
XML Android开发 数据格式
🌐Android国际化与本地化全攻略!让你的App走遍全球无障碍!🌍
在全球化背景下,实现Android应用的国际化与本地化至关重要。本文以一款旅游指南App为例,详细介绍如何通过资源文件拆分与命名、适配布局与方向、处理日期时间及货币格式、考虑文化习俗等步骤,完成多语言支持和本地化调整。通过邀请用户测试并收集反馈,确保应用能无缝融入不同市场,提升用户体验与满意度。
103 3
|
2月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
72 10
|
1月前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
227 0
|
2月前
|
XML 数据库 Android开发
10分钟手把手教你用Android手撸一个简易的个人记账App
该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。
|
iOS开发
查看 app 启动时间
苹果提供的方法 在Xcode的菜单中选择Project→Scheme→Edit Scheme...,然后找到 Run → Environment Variables → +,添加name为 DYLD_PRINT_STATISTICS  value为1的环境变量。
1412 0
|
1月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
493 7