【性能】【art】编译优化总结

ART前世今生

虽然Android应用大多用Java/Kotlin编写,但是实际上Android虚拟机并不使用JVM字节码,而是将Class文件通过DX编译器(现已换成D8)编译为更加紧凑的dex文件,然后由虚拟机执行。

最开始的Android虚拟机是Dalvik,ART虚拟机由Android4.4被引入成为可选项,在Android5.0之后替换掉了Dalvik,并且在Android7.0和8.0分别进行了一系列改动,关于ART虚拟机的说明官方文档有提到,不过并不是那么好理解。

基本概念和名词

  • .dex文件:App所有java源代码编译后生成众多class文件,由DX/D8,编译为一个/多个(multiDex)dex文件,由Android虚拟机编译执行;

  • .odex文件:dex文件经过验证和优化后的产物,art下的odex文件包含经过AOT编译后的代码以及dex的完整内容,但Android8.0之后odex中的dex内容移动到了.vdex文件;

  • .art文件:art下根据配置文件生成odex文件时同时生成.art文件,主要是为了提升运行时加载odex中热点代码的速度,包含了类信息和odex中热点方法的索引,运行App时会首先根据这个文件来加载odex中已经编译过的代码;执行过speed-profile命令的app才会生成.art文件;

  • 解释器(Interpreter):用于程序运行时对代码进行逐行解释,翻译成对应平台的机器码执行

  • JIT编译(Just In Time):由于解释器方式运行太慢引入,对于频繁运行的热点代码(判定标准一般是在某个时间段内执行次数达到某个阈值)进行实时编译(在ART下以方法为粒度)执行,并且缓存JIT编译后的代码在内存中用于下次执行。由于以方法为粒度(ArtMethod)进行编译,JIT编较于解释器可以生成效率更高的代码,运行更快。

  • AOT编译(Ahead-Of-Time):应用安装时全量编译所有代码为本地机器码,运行时直接执行机器码。

ART 如何运作

4.4~7.0

最开始ART只采用AOT编译,在App安装时就编译所有代码存储在本地,打开App直接运行,这样做的优点是应用运行速度变快,缺点也很明显,App安装时间明显变长,而且占用存储空间较大。

7.0

Android N之后对于ART进行改动,重新引入了JIT编译,结合使用AOT/JIT混合编译,主要机制如下:

  1. 安装时不进行任何编译,前几次运行仅通过解释器解释运行,同时对热点代码进行JIT编译,并将这些代码的相关信息记录在一个配置文件里(data/misc/profile/cur/0/...)

  2. 设备处于空闲和充电状态时,编译守护进程读取配置文件对热点代码进行AOT编译并写入到app对应的odex文件中

  3. 再次启动应用后优先使用AOT编译过的代码,否则使用解释器+JIT编译,重复这个过程

对于一些庞大的APP,比如淘宝,有些功能可能你一辈子都不会用到,根据上述策略这部分代码就不会被编译保存,从而减少了存储空间的占用。另外,在系统升级时也避免了全量编译所有现存应用造成的时间空间消耗。

8.0

Android 8.0引入了.vdex文件,它里面包含 APK 的未压缩 DEX 代码,以及一些用于加快验证速度的元数据。怎么理解呢?这里我们需要补充一下对dex文件的编译配置和系统ROM中各类应用的默认编译方式:

编译选项(compiler filters):

  • verify:只对 DEX 文件进行代码验证,校验各部分合法性。

  • quicken:在verify的基础上优化一些 DEX 指令,提升解释器性能。

  • speed:在verify的基础对所有方法进行 AOT 编译。

  • speed-profile:在verify的基础对配置文件中列出的方法(热点方法)进行 AOT 编译。

系统ROM中各类应用默认编译方式:

  • 启动类路径代码(用于启动系统的部分代码):默认使用 speed 编译过滤器进行编译

  • 系统服务器代码(比如电量、多媒体服务代码):默认使用 speed 编译过滤器进行编译

  • 产品专属的核心应用(比如goole服务框架):默认使用 speed 编译过滤器进行编译

  • 所有第三方应用:默认使用 quicken 编译过滤器进行编译

所有第三方应用最开始都是通过quiken模式只进行了dex校验和一些指令优化,.vdex文件存放的就是经过校验后的dex代码,以便在对热点代码进行AOT编译时避免重复验证,加快速度。

总结

扯了这么多淡实际上核心内容就一句话:App安装时不编译代码只校验合法性,运行时通过解释器执行,将运行频繁的代码进行编译放到内存缓存并且记录在本地配置文件,后台线程编译配置文件记录的方法存放到.odex文件,再次运行App时优先读.odex文件中编译后的代码,然后重复这个过程。

转载自链接:https://www.jianshu.com/p/eaf7681c5bfc

单个apk编译优化:

adb shell cmd package compile -m speed-profile/speed/everything/quicken  -f  "packagename"

全量apk编译优化:

adb shell cmd package compile -m speed-profile/speed/everything/quicken  -f  -a

删除编译优化:

adb shell cmd package compile --reset  packagename

模拟充电后台dexopt操作:

adb shell pm compile -a -r bg-dexopt cmd package bg-dexopt-job

adb shell "pm list packages | cut -d ':' -f2 | xargs -n1 -r -t cmd package bg-dexopt-job"

adb shell pm bg-dexopt-job com.hh.hwid 

adb shell "dumpsys jobscheduler" > job2.txt

dumpsys jobscheduler|grep dexopt

dumpsys jobscheduler|grep com.android.server.pm.BackgroundDexOptService -A20

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
深入理解Android虚拟机ART,需要对ART的原理、架构和功能进行全面的了解。 ARTAndroid Runtime)是Android操作系统中的一种虚拟机,它在Android 5.0及以后的版本中取代了Dalvik虚拟机。ART通过对应用程序的预编译,将字节码转换为机器码,提供了更高的性能和更低的内存占用。 ART的内部架构由多个模块组成,包括编译器、运行时库和垃圾回收器。编译器模块负责将应用程序的字节码转换为本地机器码,采用了提前编译(Ahead-of-Time Compilation)的方式,将代码的热点部分提前编译为本地机器码,从而加速应用程序的执行。运行时库模块提供了与设备硬件和操作系统交互的接口,同时实现了一些Java虚拟机的功能,如线程管理和异常处理。垃圾回收器模块负责管理内存资源,通过回收不再使用的对象,提供了更好的内存管理能力。 ART提供了一些新的特性,如增强的垃圾回收、即时编译和应用程序优化等。其中,增强的垃圾回收机制使用了新的分代垃圾回收算法,能更好地管理内存资源,减少应用程序的内存占用。即时编译(Just-In-Time Compilation)可以将应用程序的热点代码实时编译为机器码,在应用程序的执行过程中提升性能。应用程序优化功能可以分析应用程序的运行状况,根据实际情况进行优化,提供更好的用户体验。 总之,深入理解Android虚拟机ART需要详细了解其原理、架构和功能,同时还需要研究相关的性能优化方法和工具。只有全面了解ART,才能更好地开发和优化Android应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值