![640?wx_fmt=gif](https://img-blog.csdnimg.cn/img_convert/e54387ef3142efb9e1af4571d99e95d1.gif)
温馨提示
请拖动到文章末尾,长按识别「抽奖」小程序。6.6*3 红包等你来拿。
1
「控件人生」公众号满月了,当了一个月的奶爸,真的不容易,眼里满含泪水,但内心却无比喜悦,终于踏出了第一步。
看着他长出了头发,长出了牙齿。。。
在满月这天,我给大家「发红包」,并没有任何套路,只是单纯的发红包。
请拖到文章底部,长按识别小程序参与抽奖,红包不大,心意最大。同时也希望「控件人生」公众号茁壮成长,努力的活下去。
想了解 dalvik 虚拟机和 Art 虚拟机的优化升级点,就需要先了解 dalvik 和 Art 。
2
第一天
![640?wx_fmt=png](https://img-blog.csdnimg.cn/img_convert/7830138548b28374fa583152d235800e.png)
「小新」第二天参加某奇艺的面试。
「小新」这次痛定思痛,决定把 dalvik 和 Art 虚拟机搞懂。
Dalvik和ART
大家都知道 Android 系统是以 Linux 为内核构建的。 Google 为了降低应用的开发难度,并适配到不同硬件配置的设备上,在 Linux 内核之上构建了一个虚拟机,主流的 Android 应用使用的是 Java开发语言,运行在虚拟机之上。
由于 Android4.4 越用越卡,为了解决这一性能问题,Google 在 2014 年推出了新的虚拟机 ART,并在 Android4.4 系统中提供给用户试用,力图从根本上改善系统卡顿的问题。
在 Android5.0 开始废弃了 Dalvik,全面推行 ART。那么 ART 对比Dalvik 又有哪些优势呢?先来了解下 Dalvik。
Dalvik 是 Android4.4 之前使用的虚拟机,使用的是 JIT(Just-In-Time)技术来进行代码转译,每次执行应用的时候(运行时),Dalvik 将程序的代码编译为机器语言执行。
随着硬件的不断提升以及追求更高性能的需求,Dalvik虚拟机越来越卡顿。
ART(Android RunTime)虚拟机,采用的是 AOT(Ahead-Of-Time)技术,在应用程序安装的时候就转换成机器语言(运行前),不再是执行时解释,从而优化了应用运行的速度。
在内存管理方面,ART 也有比较大的改进,对内存分配和回收在算法上都做了一定的优化,降低了内存碎片化程度,回收时间也缩短了。
下图是 Google 发布的使用不同性能测试工具时 Dalvik 和 ART 的得分对比:
2
3
内存管理
内存管理的优化是 ART 的一大改进。
ART 虚拟机首先会从系统空间中获取足够的空间,这些空间在没有使用的时候并不占用物理内存,只有在使用的时候才分配物理内存,在不需要的时候及时归还给系统。
ART 将分配到的空间根据需要,托管给不同的算法来进行管理,主要提供了如下几种分配算法来进行「内存分配」,它们的定义可以在 ART 源码定义中看到:
enum AllocatorType {
kAllocatorTypeBumpPointer, // Use BumpPointer allocator, has entrypoints.
kAllocatorTypeTLAB, // Use TLAB allocator, has entrypoints.
kAllocatorTypeRosAlloc, // Use RosAlloc allocator, has entrypoints.
kAllocatorTypeDlMalloc, // Use dlmalloc allocator, has entrypoints.
kAllocatorTypeNonMoving, // Special allocator for non moving objects, doesn't have entrypoints.
kAllocatorTypeLOS, // Large object space, also doesn't have entrypoints.
};
其中后面二种是没有跳转表(entrypoints)的,主要了解一下前面 4 种的分配策略:
RosAlloc(Rows of slots Allocator)的分配策略,在 Ros Alloc Space分配对象,是一种线性的分配方式,将一个大的连续空间划分为多个片,每个片中只分配固定大小的内存。这种分配方式有一个更加细粒度的结构,可以锁定独立的对象。
BumpPointer 的分配策略,在 Bump Pointer Space 中分配对象。每一次申请内存时,分配需要的 size,返回 end 地址的值。然后将 end 后移 sized,作为下一次申请的地址。这种分配采用不计数申请的方式,直到发生内存泄露 out of memory。采用 Moving GC 的方式进行回收。
DLMalloc 的分配策略,这是原 Dalvik 使用的算法 。在 Dl Malloc Space 分配对象,将 memory 划分成很多小的数据块,每一个块的前 8 个或者16 个字节作为 Header,使用链表来管理空闲的数据块。
TLAB(Thread Local Allocation Block) 的分配策略,在由Bump Pointer Space 提供的线程局部分配缓冲区中分配对象,按线程进行管理。每一个线程,从 Bump Pointer Space 中申请一个 block,在线程内使用该分配策略。由于每一个线程独立在自己的 block中分配内存,避免了同步,可以提高效率。
使用这些不同算法来分配内存,与 Dalvik 相比可以有效的减少碎片化,由于碎片化减少,相应也就减少了 GC 的次数,提高了效率。
除此之外,像 TLAB 这样的算法引入,也减少了申请内存时线程之间的竞争。在内存回收方面,ART 也提供了几种 GC 算法,GC 算法与内存分配算法相对应,关系如下表:
ART 在回收内存 memory 时,会依据进程状态选择不同的算法。同时,ART 在 GC 时采用了读写锁的机制,减少了进程被挂起的时间,因此较之于 Dalvik,GC 时线程挂起的时间也相应缩短。
2
4
代码执行
先来看一张 Google 的 Android 对 apk 的执行流程图:
可以这样来解释这张图,众所周知,Android 中可执行文件类型为 dex,Java 文件在编译成 class 文件,然后经过Android 平台的 dx 工具转换为 dex 文件后,将会同 Native code(JNI)和资源一起打包成 apk,apk 安装到手机后解压出 dex 文件。
如下命令,将 Main.class 转换成 main.dex 文件:
dx --dex --output=D:\main.dex Main.class
Dalvik 会通过 dexopt 工具将 Dex 优化,成为 Odex 文件,Odex 文件的效率比 dex 高,但其中大部分代码仍然需要每次执行时编译。 而 ART 则会将 dex 通过 dex2oat 工具编译得到一个 ELF 文件,它是一个可执行的文件。
接下来看一段简单的 Java 代码:
int a = 1;
int b = 2;
public int test() {
① int x = a;
② int y = b;
int z = a + b;
return z;
}
这段代码执行时,Dalvik 虚拟机先要把 test 方法的每句代码转译成 dex 代码,对其中的 ① ② 两句赋值语句,执行时需要在虚拟机中进行「指令读取—识别指令—跳转—实例操作」的解析过程。
而 ART 中 Java 代码都被以方法为单位编译成汇编指令,执行上面这个方法的时候,① ② 两句代码只需要直接拷贝两个寄存器的值,各需要一条汇编指令就可以完成,省去了跳转、指令读取的过程,执行效率也就大大提高了。
5
优化点
虚拟机从 Dalvik 换成 ART 后,Android 系统的性能将会得到了一定程度的提升。
不过 ART 与 Dalvik 相比也存在一些缺点,比较明显的是,apk 经过 dex2oat 预编译之后,占用的空间增加,因此 Android ROM 占用的空间更大。
手机在安装下载的 apk 时,安装时间也明显变长。转换成机械语言。
ART 虚拟机经过一系列的优化,已经不是纯的 aot ,而是解释执行 + jit + aot 。后续还会介绍,华为的「方舟编译器」。
推荐阅读
LinearLayout和RelativeLayout性能对比,你认为谁的效率更高?
长按识别小程序,参与抽奖
![640?wx_fmt=other](https://img-blog.csdnimg.cn/img_convert/fd7b07e32baafbbfae23f4ddcf28c606.png)
![640?wx_fmt=png](https://img-blog.csdnimg.cn/img_convert/129dda200a74ee8489525932ae527e18.png)
目前100000+人已关注加入我们
微信扫描参与抽奖