华为方舟编译器做了些什么,让安卓有了“丝滑”的感觉 ?

作者:CQITer小编 时间:2019-05-16 21:18

字号

华为方舟编译器做了些什么,让安卓有了“丝滑”的感觉 ?

敲黑板,先来讲几个术语:

1. JIT

全称是Just-in-time,即时编译;当Java字节码运行在JVM上的时候,JVM实时得把字节码编译成机器码就叫JIT。

2. AOT

全称是Ahead-of-time,预先编译;与JIT对应,你JIT不是实时的吗?那我先提前编译好,就是AOT。

3. IR

全程是Intermediate representation,即中间表示。中间表示是一个从原始表示到目标表示之间的中间层。

现代编译器分为前端和后端,前后端的分界线就是IR。

现代编译器的大致流程:词法分析->语法分析->语义分析->IR->优化->生成目标代码。

针对华为给出的方舟编译器的讲解,我们来看看方舟到底做了什么,以及推测一下方舟可能做了什么,或者方舟可以做什么。

1. 无需虚拟机运行

我们都知道,Java的字节码需要运行在Java虚拟机(JVM)上。JVM最重要的功能有两个:执行字节码和内存管理;我们分头来说说。

执行字节码

当JVM运行字节码的时候,会读取一条一条的指令,然后把指令翻译成当前机器的机器码并执行该操作,比如把当前栈上的两个数加起来然后再次压栈等等,这种方式叫做解释执行。

当JVM发现某一些指令经常会被执行到,每次翻译一遍会导致运行效率降低,于是JVM就把这些指令直接编译成当前机器的机器码,下次就直接执行机器码,不需要逐句翻译一遍,这就是JIT。

内存管理

写C代码的同学们,想要使用内存的时候,需要调用malloc函数动态申请一段内存,不再使用这段内存的时候,需要调用free函数进行内存释放,如果不释放,后果很严重。

而写Java代码的同学们就没有这个困惑,因为这件事被JVM承包了下来。JVM在执行字节码的过程中,会调用gc(garbage collection),gc帮我们释放不需要的内存。

方舟是怎么做的?

清楚了以上过程,我们就明白方舟编译器是怎么做的了。

既然JVM可以在运行过程中可以把字节码编译为机器码(JIT),那么为什么不能在运行字节码之前把字节码编译成机器码呢?没错,方舟就是这么做的,我们称之为AOT。

JVM的两大功能之一执行字节码就不需要了,那还有一个内存管理的功能怎么办呢?这个也好办,华为可以提供一个库,这个库实现gc所有的功能,我们称这个库为runtime。

以前我们使用JVM来运行一段字节码,现在这个流程变了,变成先把字节码(或者源程序)编译成机器码,然后带上runtime,直接运行在操作系统上,就不再需要VM了。

VM是不需要了,runtime是必不可少的,这个runtime需要处理包括但不限于以下几件事:创建对象,gc,函数调用,异常处理,锁,同步,多线程,反射。

都已经带上了这么多功能,那再带上一个解释器吧,多一个不嫌多。这些东西好像有些耳熟啊,好像安卓的ART也是这样的?我猜是的,由于Java语言本身和Java的运行时库等等一些历史原因,想推翻重来把这些东西都去掉,复杂度是很高的;所以安卓的爸爸谷歌也是在这些基础上进行修修补补。

当然,华为也可以选择不支持Java中一些动态的特性比如反射等功能,那么这个runtime是有可能简化的。到底方舟编译器和安卓已有的ART有什么不同,我们拭目以待。

2. 多语言联合优化编译器

这个很神奇对吧,C语言竟然可以和Java语言联合在一起编译。

我们知道C语言的代码编译过后是二进制文件,Java语言的代码编译过后是字节码;其实现代编译器在编译过程中有很多层中间表示,如果把源代码层看做最高层次,目标语言看成最低层次,编译过程中是逐层下降的,最后下降到目标层,和我们下楼梯是一样一样的,并不是自由落体对不对。

比如源代码经过编译器前端之后变成抽象语法树(AST),抽象语法树又可以转变为另一种更低层级的中间表示(IR),然后从IR再到目标层。

所以方舟可以定义一个中间表示(IR),把C语言和Java语言都先编译到这个中间表示层,然后在中间表示层做一系列的优化或者分析,再从中间表示层编译到机器码,这样就实现了多语言联合编译。

是不是把不同的语言编译到同一种IR上就万事大吉了呢?不是这样的!

方舟为什么要把多个语言放在一起编译?是好玩吗?当然不是!多个语言联合编译至少有以下几点好处:

减小跨语言调用开销

不同的语言之间,类型系统、调用规范、数据布局等等都不同,所以不同语言相互调用时有一些额外的开销。

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
关键词 >>华为 方舟 编译器
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接