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的配置文件操作的完美封装(使用注解 反射让配置文件操作如
    2. 【Android 内存优化】使用 Memory Analyzer ( MAT ) 工具分析内
    3. Android 中下载文件到sdcard和进度条小结
    4. 屏蔽电信流氓广告造成的诡异的问题--Android WebView 长时间不能
    5. [置顶] Android性能优化-SQLite数据库
    6. android 内部文件读取
    7. 将Android工程做成jar包和资源文件
    8. QQ音乐Android客户端Web页面通用性能优化实践
    9. Android 文件保存getFilesDir()丶getCacheDir()、getExternalFil

    随机推荐

    1. Studio 1.5模拟器启动错误android/metric
    2. HashMap 的 7 种遍历方式与性能分析!(强烈
    3. Android引用百度定位API第三方组件后导致
    4. 开发Android平板电脑程序不能全屏显示问
    5. Android消息通知
    6. Android 桌面组件
    7. Android 抽屉侧滑效果
    8. Android默认给予USB读写权限,去掉授权对话
    9. 图解 Android(安卓)事件分发机制
    10. Android中动态图形的绘制(一)