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“”内容,把新的选项更新…...

养猪废水处理设备的处理方法
诸城市鑫淼环保小编带大家了解一下养猪废水处理设备的处理方法 1.高有机负荷:猪粪尿含有大量有机物质,比如蛋白质、脂肪和淀粉等,这些有机物在水体中分解会消耗氧气,导致水体缺氧。 2.高氨氮含量:猪粪尿中的蛋白质分解…...

【React】React学习:从初级到高级(三)
3 状态管理 随着应用不断变大,应该更有意识的去关注应用状态如何组织,以及数据如何在组件之间流动。冗余或重复的状态往往是缺陷的根源。 3.1 用State响应输入 3.1.1 声明式地考虑UI 总体步骤如下: 定位组件中不同的视图状态 确定是什么…...

Rest和Http什么关系?
分析&回答 REST 定义了一组体系架构原则,您可以根据这些,包括使用不同语言编写的客户端如何通过 HTTP 处理和传输资源状态。 REST只是一种风格,不是一种标准REST是以资源为中心的 用不同的 HTTP 请求方法来处理对资源的 CRUD࿰…...

leetcode原题: 生存人数
题目: 给定 N 个人的出生年份和死亡年份,第 i 个人的出生年份为 birth[i],死亡年份为 death[i],实现一个方法以计算生存人数最多的年份。 你可以假设所有人都出生于 1900 年至 2000 年(含 1900 和 2000 )…...

K8S的介绍和架构
仅供入门 K8S的介绍和架构 一. 什么是kubernetes二、Kubernetes架构和组件 2.1 核心组件 2.1.1 Kubernetes Master控制组件,调度管理整个系统(集群),包含如下组件: a、Kubernetes API Serverb、Kubernetes Schedulerc、Kubernet…...

linux信号量
通过学习linux的信号量,对linux的信号量进行了编程。...

Jupyter Notebook 好用在哪?
Jupyter Notebook 是一个 Web 应用程序,便于创建和共享文学化程序文档,支持实时代码、数学方程、可视化和 Markdown,其用途包括数据清理和转换、数值模拟、统计建模、机器学习等等。目前,数据挖掘领域中最热门的比赛 Kaggle 里的资…...

华为云云服务器评测|基于云服务器的minio部署手册
华为云云服务器评测|基于云服务器的minio部署手册 【软件安装版本】【集群安装(是)(否)】 版本 创建人 修改人 创建时间 备注 1.0 jz jz 2023.9.2 minio华为云耀服务器 一. 部署规划与架构 1. 规…...

【网络安全带你练爬虫-100练】第22练:数据包中参数提取与处理
目录 一、目标1:GET数据包的处理 1、GET数据包中参数的提取 2、GET请求中 统计参数个数 二、目标2:POST数据包的处理 1、post中参数个数的提取 2、POST请求中 统计参数个数 一、目标1:GET数据包的处理 1、GET数据包中参数的提取 impo…...

第64步 深度学习图像识别:多分类建模误判病例分析(Pytorch)
基于WIN10的64位系统演示 一、写在前面 上期我们基于TensorFlow环境介绍了多分类建模的误判病例分析。 本期以健康组、肺结核组、COVID-19组、细菌性(病毒性)肺炎组为数据集,基于Pytorch环境,构建SqueezeNet多分类模型…...