Android 8.0 中的 ART 功能改进

在 Android 8.0 版本中,Android Runtime (ART) 有了极大改进。下面的列表总结了设备制造商可以在 ART 中获得的增强功能。

并发压缩式垃圾回收器

正如 Google 在 Google I/O 大会上所宣布的那样,ART 在 Android 8.0 中提供了新的并发压缩式垃圾回收器 (GC)。该回收器会在每次执行 GC 时以及应用正在运行时对堆进行压缩,且仅在处理线程根时短暂停顿一次。该回收器具有以下优势:

  • GC 始终会对堆进行压缩:堆的大小平均比 Android 7.0 中的小 32%。
  • 得益于压缩,系统现可实现线程局部碰撞指针对象分配:分配速度比 Android 7.0 中的快 70%。
  • H2 基准的停顿次数比 Android 7.0 GC 的少 85%。
  • 停顿次数不再随堆的大小而变化,应用在使用较大的堆时也无需担心造成卡顿。
  • GC 实现细节 - 读取屏障:
    • 读取屏障是在读取每个对象字段时所做的少量工作。
    • 它们在编译器中经过了优化,但可能会减慢某些用例的速度。

循环优化

在 Android 8.0 版本中,ART 采取了多种循环优化措施,具体如下:

  • 消除边界检查

    • 静态:在编译时证明范围位于边界内
    • 动态:运行时测试确保循环始终位于边界内(否则不进行优化)
  • 消除归纳变量
    • 移除无用归纳
    • 用封闭式表达式替换仅在循环后使用的归纳
  • 消除循环主体内的无用代码,移除整个死循环
  • 强度降低
  • 循环转换:逆转、交换、拆分、展开、单模等
  • SIMDization(也称为矢量化)

循环优化器位于 ART 编译器中一个独立的优化环节中。大多数循环优化与其他方面的优化和简化类似。由于大多数 CFG 实用工具(请参阅 nodes.h)侧重于编译而不是重写 CFG,因此通过更复杂(与平时相比)的方式进行一些重写 CFG 的优化时,会面临挑战。

类层次结构分析

在 Android 8.0 中,ART 会使用类层次结构分析 (CHA),这是一种编译器优化,可基于通过分析类层次结构所生成的信息,将虚拟调用去虚拟化为直接调用。虚拟调用代价高昂,因为它们围绕 vtable 查找来实现,且会占用几个依赖负载。另外,虚拟调用也不能内嵌。

以下是对相关增强功能的总结:

  • 动态单一实现方法状态更新 - 在类关联时间结束时,如果 vtable 已被填充,ART 会按条目对超类的 vtable 进行比较。
  • 编译器优化 - 编译器会利用某种方法的单一实现信息。如果方法 A.foo 设置了单一实现标记,则编译器会将虚拟调用去虚拟化为直接调用,并借此进一步尝试内嵌直接调用。
  • 已编译代码无效 - 另外,在类关联时间结束时,如果单一实现信息进行了更新,且方法 A.foo 之前拥有单一实现,但该状态现已变为无效,则依赖方法 A.foo 拥有单一实现这一假设的所有已编译代码都需要变为无效代码。
  • 去优化 - 对于堆栈上已编译的有效代码,系统会启动去优化功能,以强制使已编译无效代码进入解释器模式,从而确保正确性。系统会采用结合了同步和异步去优化的全新去优化机制。

.oat 文件中的内嵌缓存

ART 现在采用内嵌缓存,并对有足够数据可用的调用站点进行优化。内嵌缓存功能会将额外的运行时信息记录到配置文件中,并利用这类信息将动态优化添加到预先编译中。

Dexlayout

Dexlayout 是在 Android 8.0 中引入的一个库,用于分析 dex 文件,并根据配置文件对其进行重新排序。Dexlayout 旨在使用运行时配置信息对 dex 文件的各个部分进行重新排序(在设备的空闲维护编译期间)。通过将经常一起访问的部分 dex 文件集中在一起,程序可以因改进文件位置而拥有更好的内存访问模式,从而节省 RAM 并缩短启动时间。

由于配置文件信息目前仅在运行应用后可用,因此系统会在空闲维护期间将 dexlayout 集成到 dex2oat 的设备编译中。

Dex 缓存移除

在 Android 7.0 及更早版本中,DexCache 对象拥有四个大型数组,与 DexFile 中特定元素的数量成正比,即:

  • 字符串(每个 DexFile::StringId 一个引用),
  • 类型(每个 DexFile::TypeId 一个引用),
  • 方法(每个 DexFile::MethodId 一个原生指针),
  • 字段(每个 DexFile::FieldId 一个原生指针)。

这些数组用于快速检索我们以前解析的对象。在 Android 8.0 中,除方法数组外,所有数组都已移除。

解释器性能

通过引入 Mterp(一种解释器,具有以汇编语言编写的核心提取/解码/解释机制),Android 7.0 版本中的解释器性能得以显著提升。Mterp 模仿了快速 Dalvik 解释器,并支持 arm、arm64、x86、x86_64、mips 和 mips64。对于计算代码而言,ART 的 Mterp 大致相当于 Dalvik 的快速解释器。不过,有时候,它的速度可能会显著变慢,甚至急剧变慢:

  1. 调用性能。
  2. 字符串操作和 Dalvik 中其他被视为内嵌函数的高频用户方法。
  3. 堆栈内存使用量较高。

Android 8.0 解决了这些问题。

详细了解内嵌

从 Android 6.0 开始,ART 可以内嵌同一个 dex 文件中的任何调用,但只能内嵌来自其他 dex 文件的叶方法。此项限制具有以下两个原因:

  1. 从其他 dex 文件进行内嵌需要使用该 dex 文件的 dex 缓存,这与同一 dex 文件内嵌(只能重复使用调用程序的 dex 缓存)有所不同。已编译代码中需要具有 dex 缓存,以便执行一系列指令,例如静态调用、字符串加载或类加载。
  2. 堆栈映射只对当前 dex 文件中的方法索引进行编码。

为了应对这些限制,Android 8.0 做出了以下改进:

  1. 从已编译代码中移除 dex 缓存访问(另请参阅“Dex 缓存移除”部分)
  2. 扩展堆栈映射编码。

同步方面的改进

ART 团队调整了 MonitorEnter/MonitorExit 代码路径,并减少了我们对 ARMv8 上传统内存屏障的依赖,尽可能将其替换为较新的(获取/释放)指令。

更快速的原生方法

使用 @FastNative 和 @CriticalNative 注解可实现对 Java 原生接口 (JNI) 更快速的原生调用。这种内置的 ART 运行时优化可加快 JNI 转换,并取代现在已弃用的 !bang JNI 标记。注解对非原生方法没有任何影响,并且仅适用于 bootclasspath 上的平台 Java 语言代码(无 Play 商店更新)。

@FastNative 注解支持非静态方法。如果某种方法将 jobject 作为参数或返回值进行访问,请使用此注解。

利用 @CriticalNative 注解,可更快速地运行原生方法,但存在以下限制:

  • 方法必须是静态的 - 没有参数、返回值或隐式 this 的对象。
  • 仅将基元类型传递给原生方法。
  • 原生方法在其函数定义中不使用 JNIEnv 和 jclass 参数。
  • 该方法必须是使用 RegisterNatives 注册的,而不是依靠动态 JNI 链接。

@FastNative 和 @CriticalNative 注解在执行原生方法时会停用垃圾回收。请勿使用运行时间较长的方法,包括通常很快但一般不受控制的方法。

停顿垃圾回收可能会导致死锁。如果锁尚未得到本地释放(即尚未返回受管理代码),请勿在原生快速调用期间获取锁。此要求不适用于常规的 JNI 调用,因为 ART 将正执行的原生代码视为已暂停的状态。

@FastNative 可以使原生方法的性能提升高达 3 倍,@CriticalNative 则可以提升高达 5 倍。例如,在 Nexus 6P 设备上测量的 JNI 转换如下:

Java 原生接口 (JNI) 调用 执行时间(以纳秒计)
常规 JNI 115
!bang JNI 60
@FastNative 35
@CriticalNative 25

Android 8.0学习(31)---Android 8.0 中的 ART 功能改进相关推荐

  1. Android音视频学习系列(七) — 从0~1开发一款Android端播放器(支持多协议网络拉流本地文件)

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  2. android讨论功能,集成融云Android SDK实现在群聊/讨论组中@人的功能

    集成融云Android SDK实现在群聊/讨论组中@人的功能 可以确定的是融云SDK本身不提供@的功能,需要自定义实现. 在实现这个功能时,基本模仿微信的做法: 在列表中显示有人@了你 通知显示有人@ ...

  3. Android 8.0学习 (2)---Android HAL

    硬件抽象层 (HAL) HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现.借助 HAL,您可以顺利实现相关功能,而不会影响或更改更高级别的系统.HAL ...

  4. Hadoop-2.2.0学习之一Hadoop-2.2.0变化简介

    Hadoop-2.2.0在Hadoop-1.x的基础上进行了重大改进,主要体现在HDFS和MapReduce上.下面大体介绍HDFS和MapReduce改进的地方. 首先是HDFS联合.众所周知,在H ...

  5. android 音乐播放器mv播放功能,Android 音视频学习基础Android最简单的音频播放器| 神农笔记...

    /* *最简单的基于FFmpeg的音频播放器 *Simplest FFmpeg Audio Player *本程序实现了音频的解码和播放. * */ #include #include extern ...

  6. Android 8.0学习 (36)---Android 8.0 WebView 拍照、简易预览、二维码扫描 各种问题解决

    Android 8.0 WebView 拍照.简易预览.二维码扫描 各种问题解决 项目用到了WebView包装HTML5做成app使用,其中有页面用到了二维码和拍照上传功能.本人从未做过android ...

  7. Android8.0 学习 (17)Android国际化(多语言)实现,支持8.0

    Android国际化(多语言)实现,支持8.0 前言 最近因为项目中使用了国际化,所以正好研究了下实现方法: 首先说下项目需求: 可以随着系统切换语言而切换语言,不支持的语言显示默认 用户可以选择语言 ...

  8. Android OpenGL(二) 学习《Android 3D 游戏开发技术宝典 -openGL ES 2.0》

    note: 1 1-4章相关基础 2 5-8章重点 3 9-15章重点的进阶 4 16-19章相关技术:物理,传感器,事件交互. 5 20-22章 实例. 第一章 基础环境 第二章 游戏相关开发基础 ...

  9. 【Android 12 AOSP学习】Android内置第三方apk到系统

    这篇文章将介绍如何在Android系统中内置第三方apk 一.准备工作 编译好的Android源码 Android apk文件:也就是安卓应用安装包 二.步骤 (1)在源码packages/apps目 ...

最新文章

  1. 2022-2028年中国K酸行业发展现状及前瞻分析报告
  2. mysql连接卡死,很多线程sleep状态,导致CPU中mysqld占用率极高(问题原因还待考证)...
  3. 史上最纯洁的女孩,看到我实在被雷到了。
  4. iOS 为tableview添加新的cell类
  5. [html] 移动端如何禁止用户手动缩放页面?
  6. Firefox Test Pilot 计划正式关闭
  7. Pro Git 读书笔记
  8. mysql视图改造实体表_数据库视图改了对基表
  9. python怎样终止程序_python终止程序
  10. MATLAB2016笔记(六):数据可视化
  11. 3dmax:3dmax三维VR渲染设置(【DMC采样器】、【Vray默认置换】、【Vray系统】、【Vray日志】、杂项选项、灯光属性)之详细攻略
  12. 你真的会写for循环吗?来看看这些常见的for循环优化方式
  13. 概率论与数理统计公式
  14. 华为RH2288 V3分区并装系统
  15. 微信小程序输入框大全
  16. pyside2 系列之介绍,安装,简单例子
  17. php 短信验证 云之讯,python3.7实现云之讯、聚合短信平台的短信发送功能
  18. (eblog)8、消息异步通知、细节调整
  19. Linux中yum yum yum
  20. 1504: 变态杀人狂 时间限制: 1 Sec 内存限制: 128 MB 提交: 21 解决: 10 [提交][状态][论坛] 题目描述 变态杀人狂三师弟想到一个杀人游戏 游戏规则如下: 三师

热门文章

  1. RT-Thread下的串口驱动程序分析
  2. 【Shell教程】一----什么是Shell
  3. SPI原理超详细讲解---值得一看
  4. mysql 某列加全文索引_MySQL使用全文索引(fulltext index)---高性能
  5. html5仿qq空间,JS实现的仿QQ空间图片弹出效果代码
  6. linux指令 sed,Linux命令sed
  7. apache 配置php 版本错误u,PHP+Apache+MySQL 在配置环境时遇到的问题
  8. 用到oracle是不是就是cs架构,用Oracle 的2Tier协议录制脚本模拟CS系统测试的案例和注意事项pdf...
  9. Mysql之慢查询日志详解
  10. git--常用小命令