Android性能优化:让App启动更加快速

App的启动实际上设计到体验性问题,特别在一些用户常用的手机,如微信、支付宝等使用评率频繁,如果应用不存在后台,也是重新启动,既冷启动的情况下,启动速度如果很慢,那对用户来说是无法忍受的,因此对App的启动就显得有必要。

Multidex多dex加载优化

Android4.4及以下使用的是Dalvik虚拟机,应用在安装的时候已经对主dex进行dex opt优化了,dexopt的作用主要对dex文件进行verification和optimization,对dex文件的字节码进行优化。而之所以加入Multidex,主要是在进行dex文件方法数的限制,一个dex文件的方法数定义的类型为short类型,最大只能支持到65535,因此,若一个dex文件超出改方法数就会导致方法找不到,不在范围内。而Multidex既是谷歌用于解决方法数超出的额问题。

MultiDex做了多dex处理,在首次启动app的时候,才对除了主dex之外的dex进行dexopt处理。对其他的子dex进行dexopt处理是在application初始化的时候执行的,而既对应的application是能被dexclassloader加载的,因此在应用安装的时候,相关的application类是放进主dex中并进行了dexopt优化的。查找类的过程涉及的类如下图,因此,在dexopt过程中,主要涉及的类就是DexPathList这个类中,通过循环遍历数组dexElments,从DexFile的loadClassByBinartName方法中加载相关的类,接下来我们分析MultiDex是怎么处理的时候就可以看到。

MultiDex处理多dexopt的过程如下:

这个过程是在主线程进行的,而耗时操作分别有提取dex、压缩dex为zip文件以及dexopt操作。而其中提取dex的过程中,是使用循环遍历除main dex之外的其他dex,以及在opt dex,既makeDexElements方法中,也是循环遍历文件进行dex opt的操作。因此,主要的优化点就在这几步中。一般的,若不支持到2.3的话,程序没必要经过压缩为zip文件,压缩为zip文件主要是因为向下兼容2.3的。

至于单向的循环遍历操作,可以并发解压抽取apk中dex,使用FutureTask,可以等到所有的dex解压抽取完成,这里dex需要归并成满足CPU个数的线程个数,充分利用资源的情况下,保证dex解压后是不变的。

而在makeDexElements中,同样也是单向的循环对提取出来的dex文件进行opt操作的,opt dex是在进程中进行的,同样的,仍然充分利用资源,并发济宁dex opt操作。

经过这些优化之后,App 多dex的加载从400ms降到200ms左右。

App启动过程相关初始化优化之线程治理

在App的启动的时候,为了避免在主线程中做太多影响主线程运行的操作,我们会把一些逻辑放到子线程中进行,一般情况下可能会存在开启多个子线程,然后线程之间有先后的顺序,这在应用程序启动的时候是经常见到的。如下图,任务从开始Task开始,TaskC在执行之前,需要依赖TaskA和TaskB执行完成,同样,TaskD也需要TaskC和TaskD完成,Project在继承关系上集成Task的,其实也是一种Task,只不过一个Project会包含多个Task,其实就是嵌套的关系。这种关系实际上就类似PERT模型,是一个有向的多线图,一个Task得等前面多个线程完成才能执行。若当前Task后面没有紧跟具体任务Task,那么就直接运行结束Task。数据结构其实相对简单,使用双向的链表,用于记录前向所有的Task以及后向紧跟的Task。结合链表的添加和移除来判定是否执行当前Task,如前向Task列表为空,则立即执行当前Task,如后向Task列表为空,则立即执行结束(Finish)Task。

在我们App启动阶段,我们可能需要读取各种SharedPreference文件、可能需要初始化一些第三方apk,可能希望能提前请求加载首页的数据,可能希望读取服务配置,用于更新业务需要的配置,如此种种,我们可以根据具体需要在应用启动的时候,可以在子线程进行。而主线程会通过发送消息的方式等待子线程初始化完成,最后归拢到主线程进行页面刷新等。

通过启动时,把一些操作交给子线程处理,从而能高效启动App,而这一部的优化而使得App的启动时间从5369ms减少到3739ms。

减少GC

在我们启动过程中,我们需要查看下这个过程是否发生了GC,因为GC过程中,会存在短时的除了GC回收线程之外的其他线程进入睡眠,另外还存在锁堆的情况,这些都能造成性能变慢的原因。GC的判断是需要分配的内存和已分配的内存达到一定的范围。和Java堆相关的三个参数分别为堆最小空闲值、堆最大空限值以及堆目标利用率。通过这三个值来使得GC的次数达到最小。因此,在App初始化的时候,尽量减少大堆对象的使用,减少不必要的局部对象。

此外,在启动的时候,我们要充分保证主线程能尽量占有CPU,从而让主线程能正常执行页面加载刷新操作。因此,有必要注意IO相关的操作,尽量用空间换时间、减少SP线程和数据库线程操作占用的CPU时间、资源文件的读写、数据读写,以及优化类的加载过程等来提升性能。

减少IO操作

启动过程避免不了涉及IO的操作,资源的加载、类的加载、数据库操作、文件加载等等。IO的优化对启动的影响至关重要。尽量减少IO的重复读取磁盘,充分利用pagecache缓存、减少pagecache污染,用最少的磁盘IO,读取尽可能多的文件,因为磁盘IO读取以block为单位,一般block的大小为4KB、也就是说一次磁盘IO读取至少4KB,因此要充分利用4kB的空间大小,而我们知道,类加载是我们经常需要用到的,那么在启动阶段如果对经常用到的类进行重排,而类的大小一般又比较小,那么一来可以在没有page cache命中鹅情况下,减少磁盘IO次数,二来为更多的类加载提供命中page cache的可能。使用的方式就是在findclass中使用如下的方式:

然后我们利用Facebook的Redex添加如上的配置的文件,如下:


同样的,我们也需要对文件进行重排,从而减少磁盘IO,那么在启动阶段主要也是在研发阶段统计存在资源(如dtawable、layout、assets等)的调用顺序,形成一个调用顺序文件,然后度量相关的文件哪些是命中了page cache,哪些是真是磁盘IO的,这样我们就可以结合Redex工具来进行重排列,当然,每次要手动去处理哪些需要重排序会有点低效,最好做成自动化,自动形成重排序文件。

优化类加载过程

类的加载机制包括加载、验证、准备、解析、初始化,其中验证阶段需要校验方法的每个指令、是一个比较耗时的操作,通过Hook去掉验证环节。

总之,在启动的时候,我们要充分保证主线程能尽量占有CPU,从而让主线程能正常执行页面加载刷新操作。因此,有必要注意IO相关的操作,尽量用空间换时间、减少SP线程和数据库线程操作占用的CPU时间、资源文件的读写、数据读写,以及优化类的加载过程等来提升性能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容