首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Android N 中的ART

Android N 中的ART

作者头像
用户9732312
发布2022-05-13 17:58:38
发布2022-05-13 17:58:38
1.4K0
举报
文章被收录于专栏:ADAS性能优化ADAS性能优化

我们知道在Android N 中对其 ART做了比较大的变化。主要是同一程序的代码可能同时运行在本地机器码(编译)、解释和JIT(Just In Time)的混合运行模式,并且不同的用户,同一应用程序的代码,可能运行不同的编译代码。因为有了Profile-guided JIT/AOT Compilation,那么不同的用户行为对同一app可能会有不同的编译结果。N 上做此变化的其目的是为了在安装时间、内存占用、电池消耗和性能之间获得最好的折衷。

ART是在Android KitKat引入并在Lollipop中设为默认的运行方式。ART的主要特征之一就是安装时对应用的AOT编译。这种方式的主要优点就是优化产生的本地代码性能更好,执行起来需要更少的电量。劣势在于安装文件所需的空间和时间。在Lollipop和Marshmallow(译者注:Android 6.0)中,大的应用需要数分钟才能安装完。为了改变这种状态,Android N实现了一个混合模式的运行环境。应用在安装时不做编译,而是解释字节码,所以可以快速启动。ART中有一种新的、更快的解释器,通过一种新的JIT完成,但是这种JIT的信息不是持久化的。取而代之的是,代码在执行期间被分析,分析结果保存起来。然后,当设备idle和充电的时候,ART会执行针对“热代码”进行AOT编译,其他代码不做编译。为了得到更优的代码,ART采用了几种技巧包括深度内联。

对同一个应用可以编译数次,或者找到变“热”的代码路径或者对已经编译的代码进行新的优化,这取决于分析器在随后的执行中的分析数据。

这种混合使用AOT、解释、JIT的策略有如下优点:

  • 即使是大应用,安装时间也能缩短到几秒
  • 系统升级能更快地安装,因为不再需要优化这一步
  • 应用的内存占用更小,有些情况下可以降低50%
  • 改善了性能
  • 更低的电池消耗

JIT architecture

JIT compilation works in this manner:

  1. The user runs the app, which then triggers ART to load the .dex file.
  2. If the .oat file (the AOT binary for the .dex file) is available, ART uses them directly. Note that .oat files are generated regularly. However, that does not imply they contain compiled code (AOT binary).
  3. If no .oat file is available, ART runs through either JIT or an interpreter to execute the .dex file. ART will always use the .oat files if available. Otherwise, it will use the APK and extract it in memory to get to the .dex incurring a big memory overhead (equal to the size of the dex files).
  4. JIT is enabled for any application that is not compiled according to the "speed" compilation filter (which says, compile as much as you can from the app).
  5. The JIT profile data is dumped to a file in a system directory. Only the application has access to the directory.
  6. The AOT compilation (dex2oat) daemon parses that file to drive its compilation.

Android N的编译模式

compiler_filter.h,我们可以看到dex2oat一共有12种编译模式:

代码语言:javascript
复制
enum Filter {   
    VerifyNone,           // Skip verification but mark all classes as verified anyway.
    kVerifyAtRuntime,     // Delay verication to runtime, do not compile anything.
    kVerifyProfile,       // Verify only the classes in the profile, compile only JNI stubs.
    kInterpretOnly,       // Verify everything, compile only JNI stubs.
    kTime,                // Compile methods, but minimize compilation time.
    kSpaceProfile,        // Maximize space savings based on profile.
    kSpace,               // Maximize space savings.
    kBalanced,            // Good performance return on compilation investment.
    kSpeedProfile,        // Maximize runtime performance based on profile.
    kSpeed,               // Maximize runtime performance.
    kEverythingProfile,   // Compile everything capable of being compiled based on profile.
    kEverything,          // Compile everything capable of being compiled.
};

以上12种编译模式按照排列次序逐渐增强,那系统默认采用了哪些编译模式呢?我们可以在在手机上执行getprop | grep pm查看:

pm.dexopt.ab-ota: [speed-profile] pm.dexopt.bg-dexopt: [speed-profile] pm.dexopt.boot: [verify-profile] pm.dexopt.core-app: [speed] pm.dexopt.first-boot: [interpret-only] pm.dexopt.forced-dexopt: [speed] pm.dexopt.install: [interpret-only] pm.dexopt.nsys-library: [speed] pm.dexopt.shared-apk: [speed]

其含义如下,

  1. install(应用安装)与first-boot(应用首次启动)使用的是[interpret-only],即只verify,代码解释执行即不编译任何的机器码,它的性能与Dalvik时完全一致。
  2. ab-ota(系统升级)与bg-dexopt(后台编译)使用的是[speed-profile],即只根据“热代码”的profile配置来编译。这也是N中混合编译的核心模式。
  3. 对于动态加载的代码,即forced-dexopt,它采用的是[speed]模式,即最大限度的编译机器码,它的表现与之前的AOT编译一致。

总的来说,程序使用loaddex动态加载的代码是无法享受混合编译带来的好处,我们应当尽量采用ClassN.dex方式来符合Google的规范。这不仅在ota还是混合编译上,都会带来很大的提升。

Profile-guided compilation

JIT WORK FLOW

dex2oat编译

首先我们来看系统在什么时候会对各个应用做JIT/AOT编译呢?手机在充电+空闲等多个条件下,通过BackgroundDexOptService.java中的JobSchedule下触发编译优化。

代码语言:javascript
复制
 js.schedule(new JobInfo.Builder(JOB_IDLE_OPTIMIZE, sDexoptServiceName)
                    .setRequiresDeviceIdle(true)
                    .setRequiresCharging(true)
                    .setPeriodic(TimeUnit.DAYS.toMillis(1))
                    .build());

dex2oat编译参数

对于[speed-profile]模式,dex2oat编译命令的核心参数如下:

代码语言:javascript
复制
dex2oat --dex-file=./base.apk --oat-file=./base.odex --compiler-filter=speed-profile --app-image-file=./base.art
 --profile-file=./primary.prof ...

其流程:若dex2oat参数中有输入profile文件,会读取profile中的数据。与以往不同的是,这里不仅会根据profile文件来生成base.odex文件,同时还会生成称为app_image的base.art文件。

与boot.art类似,base.art文件主要为了加快应用的对“热代码”的加载与缓存。在apk启动时系统加载应用的oat文件以及可能存在的app image文件,app image的作用是记录已经编译好的“热代码”,并且在启动时一次性把它们加载到缓存。预先加载代替用时查找以提升应用的性能。

JIT 参数

  • dalvik.vm.usejit - Whether or not the JIT is enabled.
  • dalvik.vm.jitinitialsize (default 64K) - The initial capacity of the code cache. The code cache will regularly GC and increase if needed. It is possible to view the size of the code cache for your app with: $ adb shell dumpsys meminfo -d <pid>
  • dalvik.vm.jitmaxsize (default 64M) - The maximum capacity of the code cache.
  • dalvik.vm.jitthreshold <integer> (default 10000) - This is the threshold that the "hotness" counter of a method needs to pass in order for the method to be JIT compiled. The "hotness" counter is a metric internal to the runtime. It includes the number of calls, backward branches & other factors.
  • dalvik.vm.usejitprofiles <true|false> - Whether or not JIT profiles are enabled; this may be used even if usejit is false.
  • dalvik.vm.jitprithreadweight <integer> (default todalvik.vm.jitthreshold / 20) - The weight of the JIT "samples" (see jitthreshold) for the application UI thread. Use to speed up compilation of methods that directly affect users experience when interacting with the app.
  • dalvik.vm.jittransitionweight <integer>(dalvik.vm.jitthreshold / 10) - The weight of the method invocation that transitions between compile code and interpreter. This helps make sure the methods involved are compiled to minimize transitions (which are expensive).
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android性能优化 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档