华为方舟编译器远没有你想象的那么简单
在华为P30系列的国行发布会上,华为用几页PPT引出了「华为方舟编译器」这个神奇的新东西,华为将其称作是「Android的性能革命」,并大方地将其开源,希望App的开发者们都能用到它。
这项技术已经被华为纳入了EMUI9.1,能够升级到EMUI9.1的用户都可以享受到它带来的性能提升。网络上已经有不少的网友用正常版本的微博和方舟编译器编译的微博进行了对比,二者的启动速度、滑动的跟手性等都有明显的区别。
在进行今天的文章前,笔者先和大家普及一下现有Android应用运行的工作机制、原理。
Android所有的应用在编译打包的时候实际上是都打包成了字节码,而我们的手机CPU并不认识字节码,它们只认识机器码。于是我们需要在App和CPU之间添加一位「翻译」,App才能够正常执行。
这和一些Java应用需要通过JVM执行类似,在Android中,App需要依赖Dalvik才能执行。
在Android4.x时代,系统都采用的动态解释执行+JIT这一套方案来执行App,即App的字节码会在运行时由Dalvik虚拟机直接解释成机器码执行,或通过JIT即时编译成机器码执行。
这是典型的「边解释边执行」模式,华为在发布华为方舟编译器的时候也提到了这点。
Android5.x开始,Google对App的执行模式进行了优化,引入ART取代古老的、缓慢的Dalvik。
ART在进入Android之初自带了一个AOT(AheadofTime)编译器,这个编译器将会在App安装的过程中直接将所有的Dex字节码编译成机器码,之后App每次执行都执行的是机器码,而不是字节码。
由于App执行的过程中省去了中间的「翻译」,所以其执行效率自然是更高的。这是Android5.x到6.x在使用的方式,从描述上来看,它和华为方舟编译器是很类似的,即所有的代码都预先编译成机器码,App在运行时直接运行机器码,省去中间的转换过程,提升执行效率。
这个方法确实是高效的,能显著提升性能,但是它却有两个致命的缺点,一个是慢,一个是大。
完全AOT编译是在App安装的过程中进行的,这会使得App的安装过程变得相当慢,碰到淘宝这种大型的、逻辑复杂的App,其安装速度会慢到令人发指。
如果你有使用过那个年代的Android手机,你会发现系统每次更新后会在第一次开机的时候出现「Android正在升级,正在优化应用」,这实际上就是Android5.x的机制引起的,即所有的系统应用在第一次开机时都会被预编译成机器码,以提升系统的整体性能。
如果恰好你在那个年代用的Android手机性能很一般,例如搭载的处理器是联发科的中低端处理器,有的时候这个优化需要跑半个小时及以上,非常地烦人。
所以在后续的Android中这样的机制被舍弃了。
至于「大」这个缺陷,它在Android5.x的年代是体现得更加严重,因为当时大量的手机闪存都是16GB、32GB。App的字节码都转成机器码会让一个App的体积急剧膨胀,这会使得应用更加吃用户的存储空间。
在那个年代你可能会经常遇到「手机没装几个应用空间就不够了」的情况,这也和当时的Android对App的处理有关。
从Android7.x开始,所有的App改为了「混合执行」的模式。在日常生活中我们使用App可能只会很频繁地用到其个别的功能,很多功能平时并不是常用的。
在你使用App的过程中,Android会跟踪你的使用情况,它会记录下你使用过程中App经常运行的代码块,并将其编译成机器码,其余部分则采用老套的「边解释边执行」的方式去运行。
这很好地解决了App安装速度很慢、安装后体积庞大的问题,但相较于Android5.x时代的方法,这样的「混合执行」是要牺牲一些性能的,属于一个折中的、平衡的方案。
Google仍然在持续优化这一套方案,在Android8.0上他们对解释器进行了大概,提升了App的执行效率,在即将到来的Android10.0上,他们还会向开发者提供「预置热点代码」的功能,这样一来在应用安装好后,系统就会将一部分代码预先编译成机器码,提升应用的运行效率。
然而虽然Google这么做确实可以进一步优化混合执行的效率,但混合执行永远不可能达到将App预编译、只执行机器码那么高的效率。
华为方舟编译器强调的就是「只跑机器码」,而且是「全程都只跑机器码」。
这意味着从应用安装后,应用跑的就是机器码,这和Android5.x时代Google的做法是一样的。
那么问题就来了,华为的方舟编译器究竟只是一个类似AndroidRuntime的东西,在App安装的时候对App进行编译,还是一个比它还要高端的东西呢?
在发布会上,华为提到了一个细节,他们表示这个编译器是给 App 开发者提供的,这意味着这个编译器本质上并不是一个内置在手机系统里的东西,而是一个给开发者使用的工具,或者说工具链。
综合华为之前在自己开发OS的新闻,方舟编译器甚至有可能是华为自研OS的一部分,它的存在能够让应用开发者轻松地将现有的Android工程编译成适合华为写的Runtime的应用,进而能够兼容地运行在华为自己的OS上。
华为之所以创造这个方舟编译器,很有可能不只是为了提升Android的性能那么简单。
华为方舟编译器有两个点能够大幅度提升Android的性能,第一个是它是一个面向开发者的工具,这意味着它编译的是开发者编写的工程,从源代码直接编译成机器码,将二进制打包到APK中。
这是一个相当有趣的思路,方舟编译器是在开发者的电脑上完成的编译这个操作,这意味着编译和用户以及用户的手机没有任何关系,在开发者的电脑上,华为可以将这个编译的优化做到极致,编译出尽可能高效、简洁的机器码,同时避免了App安装时间长和App体积过大的问题。
另一点是华为在编译器中加入了和OS的交互,不过这可能只能在EMUI上实现。在编译的过程中,编译器会在编译时对一些特别的代码进行标记,例如IO密集的代码等等。系统在执行它的过程中看到了这些标记,就会预先对系统资源进行调配,这和GPUTurbo是差不多的思路。
这么一来,应用的执行将会变得非常通畅,进而总体的性能会有一个大幅的提升。
如果华为真的已经在EMUI中加入了一套配合方舟编译器做的自己的Runtime,那么即使华为开源了这个编译器,那么开发者也只能给EMUI编译更快的应用,其他厂商是偷不走这个技术的。
从华为开源它的动作来看,笔者个人认为华为应该是做了一套自己的Runtime实现,配合这套Runtime,经过方舟编译器编译出来的App在性能表现上才会有大幅提升。它可以兼容其他厂商的手机,但是性能表现是会打折扣的。
由于华为只开源了编译器这个部分,所以其他厂商根本没有办法复刻华为通过方舟编译器给App运行性能带来的提升,因为其他的厂商根本没有办法通过这个编译器反推出Runtime。在这个点上,华为牢牢地限制住了竞争对手。
华为的这个举动可以说是在对Android生态做进一步的分裂,华为最近是动了EMUI底层方面的东西,不知道华为是不是已经开始在向自己的OS过度了,如果是的话,这一次开放方舟编译器将会是一个关键的节点。