原创内容,转载请注明出处,多谢配合。
最近做了dex2oat相关优化,那么简单总结下一些相关流程与知识点。
这里虚拟机相关基础知识这里不赘述了,不清楚的可以移步之前的文章:
热修复&插件化(二)-虚拟机
启动耗时分析(三)-ART编译分析
我们都知道,ART虚拟机引入了AOT预编译,最终编译任务是交由dex2oat来处理的。dex2oat是一个Android系统的二进制可执行文件,保存在system/bin目录下。
相比传统的JIT编译来说,dex2oat编译的二进制文件是持久化的,当前编译耗费时间更长、存储空间占用也更大,但是换来的是下次直接执行持久化的机器码,大幅度提升运行效率。
另外,需要注意的是:dex2oat执行编译操作的时候,会起j参数后面跟的线程数去执行(常见的-j6),在大量执行dex2oat操作的场景下,CPU占用率会非常高,很大概率会占用大核和超大核影响到用户前台操作,甚至出现卡顿和黑屏。这里优化策略我肯定不会写出来的,哈哈,但是呢可以把一些相关的流程与知识点总结下。
top -t -m 10
PID TID PR CPU% S VSS RSS PCY UID Thread Proc
23836 23840 4 11% R 1297936K 59156K bg u0_a14 Compiler driver /system/bin/dex2oat
23836 23841 7 11% R 1297936K 59156K bg u0_a14 Compiler driver /system/bin/dex2oat
23836 23843 5 11% R 1297936K 59156K bg u0_a14 Compiler driver /system/bin/dex2oat
23836 23844 6 11% R 1297936K 59156K bg u0_a14 Compiler driver /system/bin/dex2oat
23836 23836 3 11% R 1297936K 59156K bg u0_a14 main /system/bin/dex2oat
23836 23845 7 11% R 1297940K 59156K bg u0_a14 Compiler driver /system/bin/dex2oat
23836 23842 3 11% R 1297936K 59156K bg u0_a14 Compiler driver /system/bin/dex2oat
23836 23839 7 11% R 1297936K 59156K bg u0_a14 Compiler driver /system/bin/dex2oat
本篇文章先对目前触发dex2oat操作的通路进行简单梳理:
一、触发路径
这里是原生的方式:
路径 | 描述 | 编译方式 | 编译内容 |
---|---|---|---|
Install | 应用安装通过installd触发的编译 | speed-profile | 主apk |
OTA升级 | 系统升级通过installd触发的编译 | verify | 主apk |
load dexFile | 动态加载插件直接通过虚拟机触发的编译 | quicken | 插件 |
postboot | 开机1分钟后,针对全部安装的7天内未使用且过期的应用通过installd触发的编译 | verify | 主apk |
idle | 同时满足充电、idle状态且24小时内只触发一次,主apk通过installd触发编译,插件通过虚拟机触发编译 | speed-profile | 主apk 和 插件 |
二、触发条件
dex2oat触发之前会先做条件判断,来决定是否需要做:
- dex文件完全没有编译过。
- 已经生成了odex,但是后续执行了更高优先级的compile filter,因此需要重新编译覆盖。
- OTA系统升级,boot image发生了变化。
所谓的过期就是针对后两点而言的。
从编译通路我们可以看到,触发dex2oat编译的方式主要有两类:
- 经过PMS由installd触发。
- 动态加载插件是直接由虚拟机触发。
这两类路径分别由后面篇文章来分析:
Android 9.0 ART编译分析(二)-Installd触发dex2oat编译流程
Android 9.0 ART编译分析(三)-虚拟机触发dex2oat编译流程