Android 开机速度优化-----ART 预先优化


Android开机速度


我们知道在L及以后的版本中,当系统升级后,或者恢复出厂设置后,或者第一次开机,其启动时间往往很长,短的有3-4分钟,而长的多达10分钟,那么是原因导致的,我们将分析其原因.

ART 的前世今生

我们知道,Android的最初的几个版本,Androidapp 运行在Dalvik,完全是解释性执行.Android2.2,GoogleJVM中常用的技术JIT带进了Dalvik,并且增加了多线程的处理能力.随着岁月的流失,科技的进步,屌丝用户期望的提高,手机厂商拼分数,拼情怀,拼硬件,跟踪赵氏族人的style.终于Android 手机的HW,singlecore 到了8cores,10 cores. RAM 也从256M,512M, 1G, 2G, 3G 6G.内部存储也从256M到了128G,256G.Google也顺应潮流,终于在,正式推出ART.

下面是ART 的架构图.



首先ART兼容Dalvik.也就是说ART 能运行”dex”(Dalvik执行文件).因此对Androidapp的开发者来说,他们没有什么区别.两者最大的区别是:ARTJIT(Just-in-Time)变成了AOT(Ahead-of-Time).JIT需要在每次运行app时都需要执行一遍,AOT 只需要执行一次,而后续再运行此app是不需要再执行,其明显提高了性能.当然ART 这样做,也是有代价的,那就是以空间换时间.ART能对应用的所有code做优化,其把bitcode 编译为ELF文件.ELF文件也往往比odex文件大很多.JIT 只能对local/method做优化.ART的另一个缺点是其第一次执行优化时需要更长的时间.这也是导致第一次开机时间过长的原因.


此外在ART,GC 也有了很大的提高.我们知道在Dalvik,GC首先需要”stopall the world”.然后再执行GC.其后果就是影响app的性能.其表现为Janks或者启动时间长,卡顿等.相比较DalvikGC,ART 做了如下的提高:

  • ART 中有几种不同的GC 类型,分别是MS (Mark-Sweep),CMS(Concurrent Mark-Sweep),SS(Semi-space GC), GSS(Generational Semi-space ), MC(Mark Compact ),default CMS.

  • ART ,有三种GC plan,分别是Sticky GC: free 从上次GC 以来新分配的object,这种GC plan 是最常用的,也是最经济的; Partial GC:free zyogte外分配的空间;Full GC,释放APP所有分配的Java空间.其执行时间为sticky GC < partial GC < full GC.ART 会根据heapmemory使用情况,选择GC plan.

  • ARTGC ,只有一次pause remark 阶段.Dalvik中有两次pause, 一次是Root Mark阶段另一次是remark 阶段.如下图所示.


  • ART 对前台应用和后台应用采用不同的GC 算法来来达到性能和memory 的平衡.对于前台应用采用CMS算法, CMS算法不会合并空间其好处是反应快,给用户更好的performance体验.但是其可能会导致heap的碎片较多.而对应后台引用采用SS, GSS MC 算法这些算法可以合并压缩memory空间有效的减少heap的碎片并节省memory.

预先优化

对于ART我们现在有了如下认知,

  • ART AOT(ahead-of-time)进行优化.即在install app的时候,dex 文件编译为native code 并生成OAT file(依然是odex,但其格式是ELF).

  • Dalvik相比,Performance有了较大的提升并且更节省功耗.

  • ART ,没有code cache(Dalvik JIT cache).OAT 文件直接mapmemory.

  • ART zygote 启动的时候会把初始化的class, object (boot.art) map memory 中去(大概10M 左右).在内存紧张的时候系统可以把一些proloaded classes swap out. 这样不但加快了zygote的启动速度,又提升了系统性能.

  • ART dex2oat 工具来进行Dex 文件的本地编译.其编译时间比dexopt要长.

  • OAT 文件比dexopt 生成的odex 文件要大.

归纳起来就是ART Dilvik 性能更好,其把dex文件优化为为本地代码,但是其体积大,编译时间长,运行时的性能好.

由于dex优化为OAT文件的时间比较长,所以第一次开机时间(包括恢复工厂设置/OTA升级后)可能就会比较长如果我们没有预先优化dex文件.所以我们可以用预先优化来规避这个问题, 但是其副作用就是其System image 比较大.在很多屌丝机上, 其内部存储比较小, 这就需要一个平衡.要么忍受第一次的痛苦 (开机时间长), 要么加大投入增大内部存储.

下面我们来看看相关的预先优化选项对ART优化后的OAT文件的大小和系统性能的影响.

· WITH_DEXPREOPT

我们可以在BoardConfig.mk里定义

WITH_DEXPREOPT := true

这样整个system image 就会被预先优化由于在启动时不再需要进行appdex文件进行优化(dex2oat操作)从而提升其启动速度.

· DONT_DEXPREOPT_PREBUILTS

如果我们不想把prebuilts目录中的第三方应用进行预先优化(这些应用在他们的Android.mk文件中有include$(BUILD_PREBUILT) ).而是希望这些app通过playstore 或者app提供商进行升级.我们需要在BoardConfig.mk里进行如下的定义.

WITH_DEXPREOPT :=true
DONT_DEXPREOPT_PREBUILTS := true

· WITH_DEXPREOPT_BOOT_IMG_ONLY

这个选项只是把boot image 进行预先优化.简单来说,其主要生成boot.art boot.oat.这能显著的减少systemimage 大小.但是,所有的app 都需要在第一次启动的时候进行优化需要花更长的boottime 时间.

我们需要在BoardConfig.mk里进行如下的定义
WITH_DEXPREOPT :=true
WITH_DEXPREOPT_BOOT_IMG_ONLY := true

· LOCAL_DEX_PREOPT

我们也可以控制单个APP是否需要预先优化.如果我们的APP是通过Google play 来进行升级的,或者为了平衡空间问题,我们可以在appAndroid.mk 中设置如下属性.

     LOCAL_DEX_PREOPT :=false // 不进行预先优化
     LOCAL_DEX_PREOPT :=true // 进行预先优化

· WITH_DEXPREOPT_PIC

我们知道ART system 有一份OAT file ,在运行时也会copy 一份到/data/ dalvik-cache.如果我们内部存储不够,可以enable这个选项.但是这个选项可能会影响运行时的性能.因为ART disableposition相关的优化.

device.mk 中添加,

WITH_DEXPREOPT :=true
WITH_DEXPREOPT_PIC :=true

· WITH_ART_SMALL_MODE

如果手机没有足够的空间,我们可以enable 这个宏.ART只会预先优化boot class.第一次启动的时间会大大的提升,但是也会大大影响运行时性能.因为其它的appcode 是解释性执行的.

device.mk中添加,

WITH_ART_SMALL_MODE :=true

Android 后面的版本中也许会修改成 device.mk:

PRODUCT_PROPERTY_OVERRIDES +=\
dalvik.vm.dex2oat-filter=interpret-only \
dalvik.vm.image-dex2oat-filter=speed
 
 

其它

· Preloaded Classes List

所谓preloaded classes list就是zygote在启动是需要初始化的哪些类.这将会使所有的APPshare zygote启动时初始化的类.从而APP 不需单独去初始化这些类,进而提高了效率.proloaded classes frameworks/base/preloaded-classes中定义如果我们有自己SDK并且这些类是很多应用都会用到的,我们可以把这些常用的类添加到这个list.注意如果添加过多无用的类会浪费memory,而没有把APP都会用到的基础类添加进来,也会让每一个app都有一份基础类copy,同样浪费空间.

··Image Classes List

Image classes dex2oat初始化时的预先优化的类保存在boot.art文件中这个文件在系统启动时mapmemory 中去,这部分memorymemory紧张的情况下可以被swapout. Zygote启动时,可以直接从memoryload这部分image. L ,这部分classes list preloaded classes list 相同,可以定制需要添加哪些classess.方法如下,

device.mk中添加,

PRODUCT_DEX_PREOPT_BOOT_FLAGS += --image-classes=

· ·Compiled Classes List

L的后续版本,,可以用compiledclasses list 来预先优化boot classpath 中的某些classes.这对哪些内部存储有限的手机非常有用.dex2oat在做优化时,首先会去check所优化的类是否在$OUT/system/etc/compiled-classeslist ,如果没有在这个列表中的classes则不会进行优化.只能解释性执行,这样虽然可以节省空间,但是势必影响运行时的性能.

device.mk

PRODUCT_COPY_FILES += :system/etc/compiled-classes

所以如果我们想我们的第一次开机时间比较快,那么请用预先优化吧,BoardConfig.mk里添加下面这行就可.

WITH_DEXPREOPT := true



你可能感兴趣的:(Android系统优化)