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



                        

    更多相关文章

    1. 【Android(安卓)内存优化】使用 Memory Analyzer ( MAT ) 工具分
    2. Android高手进阶教程(四)之----Android(安卓)中自定义属性(attr.
    3. 站在巨人的肩膀上学习Android开发
    4. Android(安卓)NDK Hello + JNI 与 NDK区别
    5. Android的配置文件操作的完美封装(使用注解 反射让配置文件操作如
    6. 想抢先体验Android操作系统的魅力吗?那就使用Android(安卓)LiveCD
    7. Android进程管理机制及优化(HTC&其它可参考)
    8. Android(安卓)应用程序快速启动的秘诀
    9. NPM 和webpack 的基础使用

    随机推荐

    1. android中RecyclerView添加下划线
    2. android sqlite3查询
    3. TSLib ported to Android(安卓)for touch
    4. android sqlite 增删查 demo
    5. Android所有系统资源图标android.R.drawa
    6. android 中判断有无网络连接
    7. 启动android默认浏览器
    8. Android客户端GPS定位源码
    9. Android(安卓)7.0,8.0拍照loadXmlMetaData
    10. mtk android sd卡调试