您现在的位置: 首页 > 网站导航收录 > 百科知识百科知识
apply update from adb(爱奇艺Android客户端启动优化与分析)
时间,线程,初始化apply update from adb(爱奇艺Android客户端启动优化与分析)
发布时间:2020-12-06加入收藏来源:互联网点击:
1 简介
互联网领域里有个八秒定律,如果网页打开时间超过8秒,便会有超过70%的用户放弃等待,对Android APP而言,要求更加严格,如果系统无响应时间超过5秒,便会出现ANR,APP可能会被强制关闭,因此,启动时间作为一个重要的性能指标,关系着用户的第一体验。
爱奇艺安卓APP非常重视启动速度的优化,本文将从启动过程,启动时间测量,启动优化,以及后续监控等方面分享我们在启动优化方面积累的经验。
2 启动模式
要准确的测量APP的启动时间,首先我们要了解APP整个启动过程。 启动过程,一般可以分为以下三类:
从上图可以看出,启动过程中,Cold的模式下,生命周期中做的事情最多,启动的时间最长,因此,我们以冷启动来衡量APP启动时间。启动过程中,如何判断哪些生命周期影响启动速度呢?
3 启动过程
我们知道,APP的启动和运行,就是Linux系统创建进程和组件对象,并在UI线程中处理组件消息的过程。
启动过程图:
App的启动过程,可以划分为三个阶段:
3.1 创建进程
当APP启动时,如果当前app的进程不存在,便会创建新的进程;App主进程启动后,如果启动某个组件,并且该组件设置了android:process属性,组件所运行的进程不存在,也会创建新的进程。
需要注意的是,如果在启动阶段,初始化的组件中,包含了多个进程,便会创建多次进程,BindApplication操作也会重复执行多次
3.2 创建UI线程及Handler
进程创建后,会通过反射,执行ActivityThread入口函数,创建Handler,并在当前线程中prepareMainLooper,并在Handler中接收组件的消息,我们来看一下Handler中处理的消息:
LAUNCH_ACTIVITY,启动,执行ActivityRESUME_ACTIVITY,恢复ActivityBIND_APPLICATION,启动appBIND_Service,Service创建, onBindLOW_MEMORY,内存不足,回收后台程序sMainThreadHandler中,处理的消息很多,这里只罗列了,可能在启动阶段可能会执行的操作, 这些操作都是运行在Main Thread中,对启动而言,属于阻塞性的。
Activity生命周期,自然需要在启动阶段执行,但,对于Service的创建,Trim_memory回调,广播接收等操作,就需要重点考虑,其操作耗时性。
3.3 Activity运行及绘制
前两个过程,创建进程和UI线程及Handler,都是由系统决定的,对APP开发者而言,并不能控制其执行时间,在本阶段,执行BindApplication,和Acitivity生命周期,都是可以由开发者自定义。
Activity执行到onResume之后,会执行至ViewRootImpl,执行两次performTraversals,第二次traversal操作中,会执行performDraw操作,同时通知RenderThread线程执行绘制.
从启动的三个阶段,我们可以看出,启动启动时间的长短,决定因素在于,主线程中所做事情消耗的时间的多少,所以,我们的优化工作主要集中在,排查主线程中耗时性的工作,并进行合理的优化。Android手机,系统的资源是有限的,过多的异步线程,会抢占CPU,导致主线程执行时间片间隔增大。同样的,内存消耗状态,GC频率,也会影响启动的时间。
4 分析及测量
通过上述的源码的解读,我们已经了解了启动过程,以及可能引起启动过慢的原因。接下来介绍一些常用的分析手段及时间测量方法。
I 启动分析工具,主要使用SysTrace,具体的使用方法,请参考官网文档https://developer.android.com/studio/command-line/systrace。
4.1 SysTrace分析技巧
4.1.1 UI Thread 颜色显示
绿色:Running白色:Sleeping棕色:Uninterruptible Sleep橙色:Uninterruptible Sleep - Block I/O其中10ms以内的,较短时间的Sleeping状态,不用关注,可能是由于CPU调度的时间片分配间隔引起的;较长时间的Block I/O和Sleep状态,可以确定有阻塞启动的逻辑在这个阶段运行,需要进一步对代码进行分析定位。
4.1.2 查看CPU状态及线程运行时长
查看CPU占用状态:
线程执行:
通过该阶段密集程度,反映出CPU占用率,也能在一定程度上反映出该阶段执行时间被阻塞情况;线程执行情况统计,可以查看线程执行时间排名,对执行时间较长的子线程进行优化。
4.2 SysTrace启动时间
在SysTrace图中,UI Thread中包含了bindApplication,activityStart,traversal等操作,RenderThread中包含DrawFrame等操作。这些TAG节点是源码已经添加的,可参考#3.2中介绍。
I Trace上启动时间:从bindApplication至第二次traversal完成,可认为UI第一次绘制完成,启动完成。选中开始点和结束点,可以查看过程消耗的时间。
4.3 adb shell am start -W
在统计APP启动时间时,系统为我们提供了adb命令,可以输出启动时间
I TotalTime: 表示新应用启动的耗时,包括新进程的启动和 Activity 的启动,但不包括前一个应用 Activity pause 的耗时
系统在绘制完成后,ActivityManagerService会回调该方法,统计时间不如SysTrace准确,但是能够方便我们通过脚本多次启动测量TotalTime,对比版本间启动时间差异。
4.4 埋点
通过APP启动生命周期中,关键位置加入时间点记录,达到测量目的。
4.5 录屏
录屏方式收集到的时间,更接近于用户的真实体感。
5 优化
为了让用户在进入APP之后,更快更流畅的使用服务,所以会在启动过程中,提前对一些基础库和组建进行初始化操作,这就意味着系统有限的资源会被抢占,影响启动时间。启动时间的优化,是一个平衡性能和体验的过程。
通过Systrace工具分析,我们发现爱奇艺爱奇艺安卓APP启动过程中一些问题,接下来,我们就结合具体的业务实践,进行启动问题进行优化。
5.1 区分进程初始化Application
由#3我们了解到,对于一个app而言,App内组件可以运行在不同的进程之中。举个例子: 一个APP拥有主进程,插件进程,下载进程三个进程,会在启动阶段创建相应的组件,但只有一个QYApplication继承自系统Application,创建三次进程,QYApplication中attach(),onCreate()方法都会被执行三次。
每个进程说需要初始化的内容肯定是不一样的,所以,为了防止资源的浪费,我们需要区分进程,初始化Appcation.
I 成果:对多进程应用而言,通过对初始化内容进行梳理,合理区分初始化,会大幅减少内存和CPU占用。
5.2 异步处理耗时任务
子线程处理耗时任务,主线程做的事情越少,越早进入Acitivity绘制阶段,界面越早展现。
注意:
不在主线程做耗时任务,如文件,网络等启动阶段初始化任务,尽量在异步线程处理主线程,不用等待或者依赖于子线程任务I 进一步优化:可以自建线程池,维持一定线程个数,管理任务队列。
5.3 防止多线程抢占CPU
Android系统资源有限,特别是CPU资源,理论上来说,UI线程执行的任务,也无法保证一直被调度状态,当并发的线程数过多,UI线程时间片会更短,从而导致启动时间被变慢。
下面罗列一些常见,容易造成CPU被抢占的场景:
上一篇:b5纸多大尺寸(2021年杭州市学生用品、劳保用品抽检信息)
下一篇:返回列表
相关链接 |
||
网友回复(共有 0 条回复) |