深入解析Android 虚拟机
上QQ阅读APP看书,第一时间看更新

3.5 ART机制基础

随着Android 4.4和Android L版本的推出,Dalvik VM系统逐渐被谷歌抛弃,取而代之的是ART运行机制。ART模式英文全称为:Android runtime,是从Android 4.4系统开始新增的一种应用运行模式,与传统的Dalvik模式不同,ART模式可以实现更为流畅的安卓系统体验,对于大家来说,只要明白ART模式可让系统体验更加流畅,不过只有在Android 4.4以上系统中采用此功能。在本章的内容中,将详细讲解ART技术的基础知识,为读者步入本书后面知识的学习打下基础。

3.5.1 什么是ART模式

ART模式的完整名称是Androidruntime,事实上谷歌的这次优化源于前不久其收购的一家名为Flexycore的公司,该公司一直致力于Android系统的优化,而ART模式也是在该公司的优化方案上演进而来。ART的机制与Dalvik不同。在Dalvik下,应用每次运行的时候,字节码都需要通过即时编译器转换为机器码,这会拖慢应用的运行效率;而在ART环境中,应用在第一次安装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。这个过程称为预编译(AOT, Ahead-Of-Time)。这样,应用的启动和执行都会变得更加快速。

ART模式与Dalvik模式最大的不同在于,在启用ART模式后,系统在安装应用的时候会进行一次预编译,在安装应用程序时会先将代码转换为机器语言存储在本地,这样在运行程序时就不会每次都进行一次编译了,执行效率也大大提升。从这方面来看,ART模式确实能够改善Android平台一直以来在兼容性方面的妥协,但另一方面,应用经过预编译后的容量,以及应用是否兼容该模式也是需要重点考虑的问题。因此接下来笔者也准备通过一些测试来看看ART模式目前的表现是否能令人满意。

(1)产生背景。

与iOS相比,Android的用户体验总是差强人意。随着Google的全力推动和硬件厂商的响应,Android还是跨越各种阻碍,逐渐壮大起来了。在此过程中,Google也在经历着重大的变化。它逐渐从一个只重视数据的公司,转变为一个重视设计和用户体验的公司。从Android 4.0开始,Android拥有了自己的设计语言和应用设计指导。与此同时,Google也在着手解决卡顿问题,Android 4.1使系统和应用运行都更加顺畅,而Android 4.2提升了内存管理,使得系统能够顺利运行在硬件配置低端的设备上。

但是,所有这些都没有解决核心问题,那就是应用运行环境:Dalvik VM效率并不是最高的。从Android 4.4开始,Google开发者引进了新的Android运行环境ART。Android官方将其作为其新的虚拟机,以替代旧的Dalvik VM。

根据一些基准测试,新的运行环境能够使大多数应用的执行时间减半。这意味着,CPU消耗大、运行时间长的应用能够更加快速地完成,而一般的应用也能更加流畅,比如动画效果更顺畅,触控反馈更加即时。在多核处理器的设备上,多数情况下只需激活少量的核心,或者能够更好地利用ARM的big.LITTLE架构。另外,它将会显著提升电池的续航能力以及系统的性能。

预编译也会带来一些缺点。一方面,机器码占用的存储空间更大。字节码变为机器码之后,可能会增加10%~20%,不过在应用包中,可执行的代码常常只是一部分。比如最新的Google+APK是28.3MB,但是代码只有6.9MB。另一方面,应用的安装时间会变长。至于延长多少时间,取决于应用本身,一些复杂的应用,如Facebook和Google+,会让你等待更长时间。

(2)Android系统性能提升之路。

Dalvik虚拟机作为Android平台的核心组成部分之一,允许在有限的内存资源中同时运行多个虚拟机实例。Dalvik虚拟机通过以下方式提升性能。

DEX代码安装时或第一次动态加载时odex化处理。

Android 2.2版本提供了JIT机制提升性能,号称性能提升3~5倍。

提升硬件配置,如更多核CPU、更高频率CPU、更大的RAM等。

但是Android的系统流畅度与iOS系统还是有一定差距。Android代码必须运行在Dalvik虚拟机上,而iOS直接是本地代码,性能差距也在情理之中。如果Android系统想拥有与iOS系统相同的系统性能,Dalvik虚拟机运行机制就成为Android系统性能提升唯一的障碍。

从Android 4.4开始提供了一种与Dalvik截然不同的运行环境——ART(Android Runtime)的支持。

(3)ART架构。

ART完全兼容Dalvik的字节码格式dex,因此,开发者编写软件不会受到影响,也无需担心兼容性问题。ART的一大变化是,它不仅支持即时编译(JIT),而且支持预先编译(AOT)。在Dalvik上,每次软件运行,都需从字节码编译为原生代码,ART可以只编译一次。然后,软件每次运行时,执行编译好的原生代码。预先编译也为新的优化带来了可能性。同时,这也会明显改善电池续航,因为软件运行时不用编译了,从而减少了CPU的使用频率,降低了能耗。

诞生ART也有一些缺点。其中之一是:设备首次启动以及应用的首次启动时间会变长。不过,Google宣称说,这种差别不是很大,而且他们会在这方面努力,使其接近甚至超过Dalvik。另一个缺点是原生代码占用空间更大,不过,现在设备的空间应该都足够。

(4)垃圾回收。

Android虚拟机是自动内存管理,这种方式的优点是开发者无需担心内存管理,缺点是开发者失去了控制权,依赖于系统本身的机制。Dalvik的垃圾回收机制是造成系统卡顿的原因之一。在Dalvik虚拟机下,启动垃圾回收机制会造成两次暂停(一次在遍历阶段,一次在标记阶段)。所谓暂停,就是应用的所有线程都不再执行。如果暂停时间过长,应用渲染中就会出现掉帧。用户体验上来说,就是应用运行的时候出现卡顿。

Google宣称,Neuxs 5的平均暂停时间是54ms,结果就是,每次垃圾回收启动,平均掉帧是4帧。如果应用编写得不好,情况会更加糟糕。Anandtech测试了FIFA游戏。Dalvik环境下,启动应用的几秒内,垃圾回收启动9次,应用暂停时间总和为603ms,总共掉帧为214帧。在ART下,情况有了极大改善。同样时间里,应用暂停时间总和为12.364ms(4次前台垃圾回收,2次后台垃圾回收),总共掉帧是63帧。

ART能够做到这一点,是因为应用本身做了垃圾回收的一些工作。垃圾回收启动后,不再是两次暂停,而是一次暂停。在遍历阶段,应用不需要暂停,而标记阶段的暂停时间也大大缩短,因为Google使用了一种新技术(packard pre-cleaning),在暂停前就做了许多事情,减轻了暂停时的工作量。Google承诺,他们已经把平均暂停时间降到了3ms,远远超过Dalvik的垃圾回收。

与此同时,Google还改进了内存分配系统,使分配速度加快了10倍。垃圾回收算法也进行了修改,以增强用户体验,避免应用被打断。

(5)64位支持。

ART支持64位系统,这会带来性能上的提升,加密能力的大幅改进,同时保持与现有32位应用的兼容性。与苹果不同的是,Google使用了指针压缩,以避免转换到64位后,空间占用大幅增加,其虚拟机仍然是32位指针。

Google宣称,现有Play Store上应用中,85%都可以转移到64位,剩下的15%有原生代码,需要重新编译。总地来说,转移到64位应该会在短时间内完成。

综上所述,Google兑现了其提升性能的承诺,解决了困扰Android性能的诸多问题。原来Android的一些致命弱点是因为非原生应用和自动内存管理系统,ART在这些方面做出了大量改进。总之,在应用的流畅度和性能方面,Android终于可以与iOS一决高下了。

3.5.2 ART优化机制基础

在安装应用程序时,Dalvik Runtime采用的代码优化方式是:

        dex2opt(http://124.16.139.131:24080/lxr/source/dalvik/dexopt/OptMain.cpp? v= android-4.0.4#f_
        OptMain.cpp)

而ART Runtime采用的代码优化方式是:

        dex2oat (https://android.googlesource.com/platform/art/+/kitkat-release/dex2oat/dex2oat.cc)

Dalvik运行环境和ART运行环境产生的优化代码路径及文件名都为:

        /data/dalvik-cache/app/data@app@{package name}.apk@classes.dex

ART环境产生的优化代码文件大小明显比Dalvik环境产生大。

在Android L系统中,ART模块的实现源码被保存在Android L源码的根目录“art”中,如图3-5所示。

图3-5 ART模块的源码

从源代码文件目录名称可以很清楚地了解各文件夹中相关文件的功能,其中最为主要的有compiler、dex2oa和runtime这3个文件夹,具体说明如下所示。

compiler:主要负责Dalvik字节码到本地代码的转换,编译为libart-compiler.so。

dex2oat:完成DEX文件到ELF文件转换,编译为dex2oat。

runtime:Android ART运行时源代码,编译为libart.so。