dex2oat编译模式、触发场景、命令强制执行
dex2oat简单理解就是把delvik虚拟机的可执行文件dex转化成AndroidRuntime虚拟机的可执行文件oat。
Android T版本由PKMS下发命令、native层进程installd负责具体执行dex2oat操作。installd回去调用dex2oat64完成编译工作,可以将dex2oat64理解成一个程序。源码路径:/apex/com.android.art/bin/dex2oat6
一、dex2oat的几种常见的编译模式
ab-ota ab升级时进行OTA prepare编译
speed-profile bg-dexopt 手机进入idle状态(充电灭屏半小时以上)编译
verify boot 开机过程中编译
speed core-app 开机过程或者充电时候的核心应用
quicken first-boot 首次开机过程中编译(刷机、OTA升级)
inactive verify idle时对10天内未使用过的应用转入此状态
install speed-profile 安装时编译
shared speed 通过package usage得到,被其他应用加载的dex
unknown run-from-apk 应用首次启动后编译,一般需要一定时间
first-boot: 首次开机或恢复出厂设置后的第一次开机,对应优化方式:speed-profile
boot:大部分时候是OTA升级后开机,可能在开机动画阶段,也可能是进入桌面后后台执行,对应优化方式:verify
core-app: 手软新增场景,针对TOP100应用做bg-dexopt优化时,采用此方式,对应的优化方式:speed
install:应用安装场景,对应优化方式:speed-profile
bg-dexopt: 系统记录热代码(包括apk和插件中的dex)后,在息屏idle状态下执行优化,对应优化方式:speed-profile
ab-ota:若系统采用A/B分区,在准备升级过程中,提前对应用做dexopt优化,对应优化方式:speed-profile
inactive:空间不足时,取消部分应用已经做的dexopt优化,重新做低级别的优化,对应优化方式:verify
shared:若当前优化应用执行方式为speed-profile且此应用有被其他应用加载的情况,则升级优化方式为speed
verify:只运行 DEX 代码验证。
quicken:运行 DEX 代码验证,并优化一些 DEX 指令,以获得更好的解释器性能。
speed-profile:运行 DEX 代码验证,并对配置文件中列出的方法进行 AOT 编译。
speed:运行 DEX 代码验证,并对所有方法进行 AOT 编译。
speed和speed-profile区别
speed和speed-profile是Android 编译模式中的两种选项。speed是一种编译模式,旨在最大化运行时性能,而speed-profile则是一种部分编译模式,根据profile记录的热点函数来编译,也是为了最大化运行时性能。
speed-profile是基于profile的quicken,即profile-guilde部分是speed,其余是quicken。但是安装的时候没啥profile,约等于quicken。profile是靠后续收集的,debug版本1000次,user版本10000次,会记录到每个进程的prof文件里。
每个app的profile文件都位于/data/misc/profiles/cur/userId/包名/primary.prof,profile文件用来记录运行比较频繁的代码,用来进行 profile-guide 编译,使得 dex2oat编译代码更精准。
1、run-from-apk
dex文件包含于apk文件中,apk是一个压缩包,run-from-apk的意思就是运行APP的时候再从apk中把dex解压出来,运行的时候边运行边把dex解释成AndroidRuntime可以执行的文件。这种模式显然是最慢的。一般不会有这种模式出现,下面三种特殊情况会出现这种模式:
①应用做dex2oat有花花似,为了保证系统稳定性,中断了优化。
②Android R上应用如果7天或者更长时间未使用,升级过程中会被认为是不常用应用,为了节省资源不优化这类应用。升级后这类应用将是run-from-apk状态。
③处在debug模式的应用不会进行dex2oat优化,会保持run-from-apk。
T上的项目将不会出现run-from-apk这种模式了。
2、extract
这种模式会将apk中的dex提前解压释放出来,这类性能比run-from-apk好一些,毕竟省去了解压apk的过程。S上进行ota升级后,会对升级过程中未选中的应用进行extract(7天或者更长时间未使用)。执行此模式的时候不涉及到编译,因此占用的系统资源相比其他编译模式会少很多。但是也正是由于本身没有任何除了解压之外的预处理,因此运行的时候所有的类加载都要verify,且只能解释执行,速度也比较慢。
3、verity,quicken
这两种模式相比前面的两种更进一步,verify模式不仅会将dex文件提前释放出来,还会提前做pre verify,生成vdex,从而省去运行的时候verify的步骤;quciken模式编译的时候会把dex文件编译成quciken code,quciken code是没有使用AndroidRuntime虚拟机的时候,系统dexopt的产物。但是这两种都不会编译成ota code。 quicken模式已在S上移除,R上quicken等效于S上的verify。
4、speed
系统的核心应用或者ShareuserID的应用将会是speed模式。这类模式的时候系统会对限定大小的方法以及class进行oat编译,生成对应的机器码。基本上是能编译的都编译了,可以说饥不择食了,因此十分耗时和耗费CPU资源。此类模式在应用启动时是相对来说很快的模式了。简单来理解就是编译了dex的大部分文件了。
5、everying
顾名思义就是把dex文件全部一丝不留编译成机械码,比speed还狠。特点是运行最快,编译文件占用存储空间最大。也因为占用系统资源很大,编译文件很大,这种编译模式不存在于正常的应用中,只存在于debug模式的应用中。
6、speed-profile
这是现在最常见的一种编译模式,它会根据用户的使用习惯,不断的进行再编译(当然再编译是要满足条件的)。它会将用户经常打开的页面中的类和经常使用的方法记录到profile文件中,用profile文件去指导编译,同时对于常用的class和string类型还会保存到对应的art文件中,用以启动加速。当应用进程起来的时候,会同时启动jit线程,而jit会对当前进程中的hot method进行run time编译,同时也会记录保存需要编译的方法和类名,这个就是profile文件。此类模式编译的结果是oat code。 此类模式由于有了profile的引入,因此编译触发比较特殊。是根据profile记录的差异与大小来触发编译。比如当前使用的应用记录了1000个方法,如果继续使用后记录变成了1100个方法,这个时候仍然不会触发编译(默认是20%增加)。如果profile记录的方法数量小于100或者class数量小于50,系统也会认为没有编译的必要。也正是因为引入了profile的编译,同样的系统版本,同样的应用版本,不同人使用的习惯不同,可能应用的odex文件编译大小也不同。理论上随着应用使用越久,profile信息将越完善,也越稳定,应用性能将越来越好。
static constexpr uint32_t kMinNewMethodsPercentChangeForCompilation = 20;
static constexpr uint32_t kMinNewClassesPercentChangeForCompilation = 20;
static constexpr const uint32_t kMinNewMethodsForCompilation = 100;
static constexpr const uint32_t kMinNewClassesForCompilation = 50
如果有root权限或者可以拿到应用的profile文件,有两个地方会保存profile,运行时写入的地方是:/data/misc/profiles/cur/0/包名/primary.prof, 编译时使用的是/data/misc/profiles/ref/包名/primary.prof。 采用speed-profile模式编译的应用,在data/dalvik-cache/arm64中一定会产生art文件,可以用这一点去判断编译模式,当然最好用的是用dumpsys命令去查看,使用dumpsys package +应用包名,可以看到应用的所有信息,包括UID、安装时间、权限信息、签名信息、dex2oat的状态。
7、vdex
为何要搞出个vdex文件?目的是为了避免不必要的验证Dex 文件合法性的过程,首次安装进行dex2oat时,会校验Dex 文件各个section的合法性,生成vdex文件,下次启动应用的时候就可以不用去校验。odex文件来自于vdex,odex+vdex=完整的apk dex信息。我对vdex的理解就是pre verify dex,就是做过verify验证的dex文件。 Android S 之后,谷歌更新了vdex格式,致使vdex复用成为可能。在S 之前,应用安装的时候会生成vdex,启动编译,或者充电编译时,会再生成一次,浪费系统资源。S上谷歌改进了这点,当二次编译的时候,如果是同一个apk,vdex将能够复用。 应用dex2oat成为vdex模式的原因,有且只有odex失效才会是vdex状态(注:odex是从vdex中提取内容组成)。有以下几种场景: 应用已经有odex,此时进行了mainline更新,重启后,由于mainline更新了,odex的依赖也需要更新,此时odex会失效,应用会变成vdex状态。 系统进行ota更新,应用不再常用应用内(七天内使用过),此类应用不会再升级过程中二次优化,升级完成后将是vdex状态。 需要注意。有一种vdex状态是异常的。比如桌面launcher,systemui这类在固件内已经是prebuild编译的应用,这类应用刷机后如果是vdex状态,那么意味着固件编译的时候odex有问题。(odex值dex2oat的结果)
8、总结
从上面介绍的这几种常见的编译模式中可以看出,谷歌设计这几种编译模式的目的,是让我们基于性能的角度可以自主控制dex2oat的编译模式,其策略是以空间换取时间, 想要应用启动得越快,就需要提前编译更多的方法和类,当然编译产生的文件占用的存储空间也会越来越大。
二、dex2oat常见的触发场景
1、内置应用
内置应用有两种方式可以修改prebuilt出来的模式。
第一种,配置自己的mk文件配置对应的模式,mk文件中加入如下修改LOCAL_DEX_PREOPT_FLAGS += --compiler-filter=speed
第二种方法,在PRODUCT_DEXPREOPT_SPEED_APPS配置文件中添加对应的apk model名字修改完成后,刷机后可以通过adb shell dumpsys package + 包名 查看其中的dex status 与reason确认是否配置成功,其中reason是prebuilt。
2、应用安装
安装触发场景根据APK来源不同分为三种:
2.1、 非谷歌商店,非应用商店安装
此类安装后通过dump查看 reason = install status = speed-profile
2.2、 谷歌商店安装
谷歌商店安装部分应用(谷歌商店内部有名单)安装后 reason=install-dm。此类应用是由于谷歌商店下发了profile文件,在安装过程中使用了profile。因此installd-dm一般是安装完成后就有比较好的性能。相当于已经进行过了二次编译,但也是因为这样,install-dm的安装时间比较长。
reason = install-dm status = speed-profile
3、灭屏充电
灭屏充电这种触发场景是通过job scheduler完成的,简单来说jobscheduler就是一种系统委托,当手机灭屏充电的时候,达到某一个job的触发条件,job就会自动执行起来。常见的委托条件,充电条件,idle条件,网络等。API介绍:https://developer.android.com/reference/android/app/job/JobInfo.Builder
这里着重说下idle条件,这里是原生系统定义的,目前R之前的idle状态是灭屏71分钟,R之后的版本为31分钟。也就是当灭屏时间满足半个小时的时候,所有委托idle状态的job就该起来干活了。
如何避免灭屏充电编译:
1、进行一晚上灭屏充电,进行灭屏充电编译。
2、通过命令禁止,上层重启后起作用。整机重启后失效。
adb shell setprop pm.dexopt.disable_bg_dexopt true adb shell am restart
3、停止job,每次开机设置一下,也是整机重启就失效。
adb shell cmd jobscheduler cancel android 800
adb shell cmd jobscheduler cancel android 801
当灭屏充电编译发起的时候,必然有BackgroundDexOptService 的日志打印,其中可以看到当前编译的状态(R上日志可能要少一些)。
充电编译开始:
BackgroundDexOptService:Performing idle optimizations
充电类型:
BackgroundDexOptService: schargeType is x 其中 x 如果是1 ,则是vooc充电 ,3或者4是pdqc充电,5是无线充电 充电电流设置: charging feature is on 是记录的上层设置的充电电流
充电编译中断:
BackgroundDexOptService: abort by thermal type
4、升级
升级过程会根据升级之前应用的使用记录进行选择编译,当前系统定义的是7天内未使用过的应用为不常用应用,这类应用将不在升级过程中进行升级编译。而对于升级编译的应用,为了平衡性能与升级时间,R上默认将采用quicken模式 S上默认是verify模式。
reason = boot status = verify
5、升级开机完成后
升级过程中会筛选出近期用过的应用进行优化,而针对那些未被选中的,原生则是放到了开机完成后再进行优化,这也是考虑到全部都在开机过程中做,时间太长。 在R 上这一过程的应用是采取了speed-verify模式编译,与安装场景的级别相当,因此会占用较多的系统资源,该过程会在开机完成一分钟后进行。
在S上这一过程的应用是采取了extract模式,不涉及到编译。且谷歌已调整为开机十分钟后进行,相比之前的speed-verify,该模式不涉及到编译,只是单纯的解压,当前S 保留了该功能。 reason = boot status = extract
R上默认关闭,S上可以通过以下命令临时关闭。
adb shell cmd jobscheduler cancel android 801
在Android T上谷歌将其推迟到了idle状态执行,且灭屏充电编译时该优化必须执行完成,才能进行接下来的编译。谷歌计划在Android U上彻底删除该触发类型的编译。
三、如何在systrace中查看dex2oat编译类型
以高通骁龙原生相机为例,先在trace中找到对应的进程。
Trace中一般会有OpenDexFilesFromOat,点击后面的location可以查看到应用的编译模式和触发原因。
四执行dex2oat时打印的log
BackgroundDexOptService
installd
dex20at64
四、使用命令强制执行dex2oat
一、强制编译命令
如下:adb shell cmd package compile
1、基于profile文件强制编译某个应用:
adb shell cmd package compile -m speed-profile -f +package_name
2、强制全面speed编译某个应用:
adb shell cmd package compile -m speed -f +package_name
3、基于profile强制编译所有带profile文件的应用:
adb shell cmd package compile -m speed-profile -f -a
4、强制全面speed编译所有应用:
adb shell cmd package compile -m speed -f -a
二、清除配置文件数据并移除经过编译的代码
请运行以下命令:
1、针对某个应用:
adb shell cmd package compile --reset +package_name
2、针对所有应用:
adb shell cmd package compile --reset -a
相关文章:

dex2oat编译模式、触发场景、命令强制执行
dex2oat简单理解就是把delvik虚拟机的可执行文件dex转化成AndroidRuntime虚拟机的可执行文件oat。 Android T版本由PKMS下发命令、native层进程installd负责具体执行dex2oat操作。installd回去调用dex2oat64完成编译工作,可以将dex2oat64理解成一个程序。源码路径&…...
深度学习 | TCN时间卷积神经网络模型答疑
深度学习 | TCN时间卷积神经网络模型答疑 目录 深度学习 | TCN时间卷积神经网络模型答疑问题汇总问题回答参考资料问题汇总 1.使用 TCN 进行序列建模有哪些优势? 2.TCN 的特征? 问题回答 1.使用 TCN 进行序列建模具备以下优势: 并行性。与 RNN 中后继时间步长的预测必须等待…...

Linux之修改服务端口号
本次演示以SSH服务为例,SSH默认监听端口是22,先保留了22端口,所以我们要进入ssh的配置文件添加新端口并注释或删掉原有端口。 1、使用vi编辑器修改文件 sshd_config,路径是/etc/ssh/sshd_config,找到“#Port 22”,添加新的端口号10086。 2、如果你关闭了…...
LeetCode笔记:Weekly Contest 361
LeetCode笔记:Weekly Contest 361 0. 吐槽1. 题目一 1. 解题思路2. 代码实现 2. 题目二 1. 解题思路2. 代码实现 3. 题目三 1. 解题思路2. 代码实现 4. 题目四 1. 解题思路2. 代码实现 比赛链接:https://leetcode.com/contest/weekly-contest-361 0. …...

Springboot快速搭建Web API项目
内容概述 SpringBoot最常见得用途就是web api项目。 本文介绍使用自动配置功能,通过最简洁的pom依赖,快速搭建一个示例项目。 实现的功能为:接收http请求并返回json格式的数据。 一、配置pom.xml依赖 1.引入springweb依赖 <dependenc…...

数据结构day06(单向循环链表、双向链表)
双向链表的练习代码 head.h #ifndef __HEAD_H__ #define __HEAD_H__ #include <stdio.h> #include <stdlib.h> #include <string.h> typedef int database; typedef struct double_link_list{union{database data;int len;};struct double_link_list* pre;…...

zabbix -- 新建主机
目录 一、新建主机 二、新建监控项 IP主机192.168.136.55zabbix控制端/服务端192.168.136.56zabbix被控端/客户端 一、新建主机 主机参数 名称、群组(每台主机必须属于某个主机组内)、ip、端口 创建完成,如果你的ZBX为灰色,代…...
=>符号含义
>主要有两方面的作用,一个限制属性状态,另一个简化匿名委托和Lambda 用法一:定义只读属性 public class ManPeople { public string Sex > "男";public string Name { get; set; }}public class WomanPeople { publi…...
Docker+Jenkins(blueocean)+Gitee构建CICD流水线实战
一、配置JDK 1.1 编辑profile文件 vim /etc/profile export JAVA_HOME/home/jdk/jdk1.8.0_301 export JRE_HOME$JAVA_HOME/jre export CLASSPATH.:$CLASSPATH:$JAVA_HOME/lib:$JRE_HOME/lib export PATH$PATH:$JAVA_HOME/bin:$JRE_HOME/bin 1.2 使配置生效 source /etc/pro…...

Redis快速入门
文章目录 0. Redis介绍1. Centos下Redis安装2. redis.conf配置文件介绍3. redis相关命令4.redis中发布订阅和事务4.1 发布订阅(Pub/Sub)4.2 事务 5. redis封装系统服务6. 问题与解决6.1 启动Redis报错:Could not create Server TCP listening…...
EasyExcel 修改导出的文件属性
EasyExcel 修改导出的文件属性 导出的文件有多种属性,本文只针对sheet名称进行举例 需要自定义拦截器 ExcelWriter excelWriter EasyExcel.write(fileName).withTemplate(stream).registerWriteHandler(new TemplateSheetStrategyHandler()).build()registerWriteHandler (n…...

电子班牌云平台系统——智慧校园管理工具,多媒体信息发布、走班排课、家校互通、物联控制、教务管理、考勤管理、素质评价、日常办公
电子班牌云平台源码,saas模式微服务架构 电子班牌是一款智慧校园管理工具,也是校园多媒体展示平台。智慧班牌融合了多媒体信息发布、走班排课、家校互通、物联控制、教务管理、考勤管理、素质评价、日常办公等一系列应用,是校园管理的现代化手…...

docker-compose 部署 Seata整合nacos,Postgresql 为DB存储
docker-compose 部署 Seata整合nacos,Postgresql 为DB存储 环境 详情环境可参考 https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E 我这里 <spring.cloud.alibaba-version>2021.1</spring.cloud.alibaba-version>所…...
three.js 场景中如何彻底删除模型和性能优化
three.js 场景中如何彻底删除模型和性能优化 删除外部模型 在three.js场景中,要彻底删除外部模型,需要执行以下几个步骤: 从场景中移除模型 你可以使用 scene.remove(model) 或者 scene.remove(model.children[0]) 将模型从场景中移除。如果…...

Bridge Champ举办人机对战赛:NFT游戏与传统竞技共生发展编织新格局
概要 现在,NFT与体育竞技正日益紧密地联系在一起。一些体育项目开始推出与赛事或球队相关的NFT,同时也有部分NFT游戏开始举办电子竞技赛事。这种共生发展正在改变体育竞技的生态。 笔者采访了桥牌冠军项目相关负责人,探讨NFT游戏与传统体育竞技的融合潜力。桥牌冠军近期成功举…...

Visual Studio软件_MSC_VER值(MSVC编译器版本)的获取方法
本文介绍查看Visual Studio软件_MSC_VER值的方法。 _MSC_VER是微软公司推出的C/C 编译器——MSVC编译器的一个内置宏,其值表示当前Visual Studio软件中MSVC编译器的具体版本。不同的Visual Studio软件版本对应着不同的MSVC编译器版本——无论是不同发布年份的版本&…...

02-Linux-IO多路复用之select、poll和epoll详解
前言: 在linux系统中,实际上所有的 I/O 设备都被抽象为了文件这个概念,一切皆文件,磁盘、网络数据、终端,甚至进程间通信工具管道 pipe 等都被当做文件对待。 在了解多路复用 select、poll、epoll 实现之前ÿ…...
echo、print_r、print、var_dump 、die
die()和exit()函数都有终止线程的作用 是php断点调试需要使用的最主要的函数 die()函数一般与“or”一并使用,写作“or die()” var_dump()和print_r() var_dump() 显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值&#…...

【LeetCode75】第四十四题 省份数量
目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 给我们一个二维数组,表示城市之间的连通情况,连在一起的城市为一个省份,问我们一共有多少个省份。 这…...

把DTC从Excel导入cdd的方法
本文是基于CANdelaStudio12.0讲解 问题一:当导入DTC的xxx.cdi文件报如下红色错误 可能原因:在设置具有下拉框的属性的内容时,输入的内容不在下拉框列表中 解决办法:在.cddt文件中更新“”Error Code Table“”内容,把新的选项更新…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...