OpenHarmony 目前主推的应用开发语言是js,谈到javascript多数人想当然的认为不适合用在单片机或嵌入式上,这家伙脚本语言还是解释执行肯定会效率不高,当然这是传统意义上的偏见。
之前js在web浏览器上用的很火的时候确实是这样的。
但自从出现了V8和nodejs, js逐渐的在MVVM前端,移动端H5和后端上都有了第二春。微软针对脚本语言的类型不安全也创造发明了typescript,可见重视程度不一般,基于此还创造了很流行的vscode编辑器。不过ts它最终还是先编译成了js,只是写法上更规范和安全。 google的V8引擎则更厉害,V8更加直接的将抽象语法树通过JIT技术转换成本地代码,放弃了在字节码阶段可以进行的一些性能优化,但保证了执行速度。源代码-→抽象语法树-→字节码-→JIT-→本地代码(V8引擎没有中间字节码)。
因此js造已没有传统意义上认为的低性能了。
OpenHarmony上的js,得益于方舟编译器的神威相助,自然性能也是提高了一大截。可以直接编译为机器指令执行,不需要经过解释器和虚拟机执行。有人会说js不是有种鸭子模型,编译时怎么知道类型呢,只能解释执行。这里有个限定是,OpenHarmony上的js只支持ES2015标准和严格模式(use strict),也就是说把之前那种js宽泛的用法给拒了,其实这是好事。js不断进化,越走越规范了,已不是传统脚本语言的范畴了。
方舟JS运行时组件
方舟JS运行时(ARK JavaScript Runtime)是OpenHarmony上JS应用使用的运行时。包含JS对象的分配器以及垃圾回收器(GC)、符合ECMAScript规范的标准库、用于运行ARK前端组件生成的方舟字节码(ARK Bytecode,abc)的解释器、用于存储隐藏类的内联缓存、方舟JS运行时对外的函数接口(AFFI)等模块。
下面介绍下方舟编译器的故事,之前只执行大名鼎鼎的GCC和Clang编译器,想不到我们也有这么强大的编译器,值得我们自豪,更值得好好学习和推广使用。传说华为使用方舟编译器把android应用的效能提高了40%,极力推荐使用。
方舟编译器的诞生经历过很长的过程,是一帮满腔热血的工程师在华为大平台之上经过多年的酝酿和磨砺,一步一步发展到今天,是必然的产物。
2009年下半年开始,第一批编译器工程师加入了位于硅谷的华为美研所,从此开始了华为自研编译器及工具链的历史。初创时期团队人员少,一个巴掌数得过来,但是幸运的是,这个团队经过十来年的积淀,留下了一批华人编译器专家的精华。他们平均从事编译器相关行业20+年。相应的平均年龄40+ 。 作为IT行业的研发人员,我认为这个年龄正是人生的精华,对技术的理解最透彻、精纯。同样幸运的是,华为对基础技术的持续投入,在国内也孕育了一批高达数百人的编译、虚拟机的相关队伍。里面聚集了国内最顶尖的人才。可以说,中国做编译和虚拟机的,有四分之一在华为。
编译器团队的业务从零起步,经历的产品包括多核芯片仿真、基于GDB的调试器、GCC和LLVM基础上的编译器设计,为公司主航道提供了大量的工具链,也创造了很多性能优化的奇迹。可是我一直认为,最大的收获在于培养了大量的人才 。
在经历过这些产品之后,我们感觉到华为内部纷繁复杂的产品需求,应该需要一套自主的软件编程体系来支撑。单纯凭借开源的零散的软件来定制不同的业务需求,效率低下,而且不论是对编译/虚拟机等系统软件还是应用软件团队来说,都没有积累,是很大的浪费。还有一个重要因素,我们从不同的国际大公司聚拢在一起,对这个行业非常了解,很清楚像华为这样的大公司拥有自己的编程体系是多么的重要。我们都非常渴望做这个事情。
最终促使我们下决心的是一个设计编程语言的项目。它的需求是,有没有可能开发一种新的高级语言,类似matlab,同时又能够发挥DSP的硬件能力。传统DSP软件的开发严重依赖于类似汇编的intrinsic,当芯片换代时,这样的软件不得不重新设计和实现。因此,这里很直观的就提出新语言的需求,同时兼顾产能和性能。这就是我们的高级语言Cm的诞生。这是一个在C基础之上融合了类似matlab数据类型和操作的语言。为了追求性能,大量的优化需要在高级IR就开始,即在语法树上进行彻底优化。工作的重点集中在前端,必须对语法树进行深入改造。
GCC没有被我们选中,因为它的前端过于晦涩,需要依赖lex/yacc这类工具自动生成一些代码,这些代码很难用人工去理解,而新语言的开发需要频繁的改动前端。Clang的前端是手写的,非常方便阅读,因此我们就以此为基础进行Cm的设计和实现。Cm取得了巨大的成功。但是,暴露出的问题是,在别人的开源编译器上进行深入的改造,效率太低。有很多具体问题,这里不展开。
至此,那个自主编程体系的问题又进入我们脑海,挥之不去。首先,从纯技术角度来看,华为的业务从最初的CT发展到今天的ICT,编译器工程师面对的芯片从DSP,CPU,GPU到NPU,面对的计算类型和数据访问类型种类繁多,编译器要适配的优化和实现也种类繁多,在各种差异存在的同时又有共性存在。依靠开源的项目实现上述目标,几乎是不可能的,或者说效率是非常低下的。最大的原因在于每个改动尤其是IR以及基础优化的改动,在他人的项目基础之上是很难顺利完成的。其次,从公司的业务来看,华为内部庞大的软件开发队伍以及无数的软件项目,其实是存在很多共性的,一个略微通用的软件开发全栈,从编程语言开始往下直至内核,对于多数项目是有很大收益的,特别在版本维护、演进和优化上。
基于上述现实,我们一直在思考的是,应该有一个自主设计的中间语言,也就是编译器的IR,作为一切软件编译和运行的基础。从而避免在舶来品上进行基础性的改动带来的痛苦,也不需要考虑是否跟随舶来品演进的问题,从而制定自己的技术路线。我个人坚定认为,华为庞大的软件开发体量,迫使我们必须有自主控制独立演进的软件编译分析框架。在此,我们要求这个IR具有很强的伸缩性,能够消化多数常见的语言特性,动态的或者静态(当然,很可能一下子达不到这个要求,但我愿意也能够大幅修改)。在此基础上,编译器的输出应该具有多样性,既可以直接编译成binary,也可以不同层次的IR输出,即以中间代码形式打包,类似Java的字节码。既可以直接送给硬件,也可以中间码进行多种格式的分发。下面这张图体现了我们的意思。
OpenHarmony 是真正意义上的面向未来、万物互联的全场景操作系统。想象下未来任何设备都可以发挥出自己独特的能力,且相互之间可以快速连接、能力互助、资源共享。不需要装app也不需要繁琐的操作。即便个别硬件性能不好,只要搭载鸿蒙都是可以轻松连接使用,不会占用太多的性能,设备各自发挥所长。音响效果好,里面没歌曲操控不方便,手机一滑动用音响放歌曲。手机编辑不方便,手指一划动,轮转到电脑上办公。电影正在在手机上观看,直接轮动到电视上全家观看。这些已都是现实。基于软总线技术这一伟大创新,相信有更多美好的体验在路上。
基于此,走自主研发的道路是无法回避的,特别是当前的GCC、LLVM和Open64等IR的设计是没有考虑Java这类语言的特性,包括对象模型以及各种动态特性的描述,与其在他人基础上不停打补丁,不如从头开始设计一个全新理念的IR。这也就是上图中红色的Maple IR。 对于技术人员来说,拥有一个每个细胞都具备自己基因的编译器,是多么惬意的事情。这也是大家的一点技术情节。
方舟编译器原先的名字叫MAPLE(Multiple Architecture Programming Language & Environment),这也是吻合了我们上图的意思。在开源的代码中可以看到很多maple字眼,以及文件的后缀名为.mpl以及.mplt等。MapleIR是重新设计的,跟传统编译器最大的区别在于我们在IR中引入对象的概念,也引入异常处理、同步操作等,因此,它能表达的语义比LLVM和GCC更贴近高级语言且囊括了语言的动态特性。
从上图的描述可以看出,方舟编译器是会输出中间码格式的软件包,中间码是平台无关的。这意味着未来的规划中,我们能够服务于一个分布式、多设备的系统,各设备接收的软件包可以是二进制或者中间码格式。根据设备的能力大小,中间码所包含的信息可以不同。为了实现这个能力,方舟引擎应运而生。这是针对中间码的执行引擎,类似于Java虚拟机。所以一个设备既可以采用直接运行机器码,也可以采用方舟引擎运行中间码。不同于Java虚拟机的是两个方面。一是,方舟引擎输入的Maple IR,这是瞄准多语言的,因此,它比Java字节码的表达范围大了很多。只要能编译成Maple IR,引擎就可以执行。二是,方舟引擎未来要包含仿真能力,也就是说,开发人员在没有实际硬件的条件下,可以仿真一些设备并运行方舟软件。
方舟最早的产品可以追溯到2016年,是JavaScript程序的编译器以及虚拟机,代号为MapleJS。它的目标设备是IoT。配合华为的LiteOS,可以支撑多数的IoT小设备。MapleJS的整体内存消耗在十几KB级别,好于三星的JerryScript。
最近火热的方舟编译器的产品是针对安卓系统下面的Java程序的静态编译(原来代号叫MapleJava)。把Java代码直接编译成机器码,所有的动态语义都通过静态方法来解决。这样的话,Java虚拟机就不用存在了。在安卓系统中,ART(Android Runtime)也不需要了。最常见的卡顿原因,即GC,是通过Reference Counting解决(环引用通过一个按需触发的backup GC搞定,触发频率低到可以忽略不计)。这也是方舟取得流畅度提升的一个主要原因。综合来讲,做静态编译的最强大的地方在于看到更多的程序信息,这其实是为我们将来更宏伟的计划做准备。大家常见的虚拟机JIT编译可以得到profiling信息的优点,在静态编译通过训练一样可以获得,只是两者在信息类型和数据量上各有千秋。
前面图中描述的MapleIR,其核心设计思想是能够兼容常见的几种语言。这个要求背后隐藏的一个长远的设想就是消除跨语言的障碍。举个例子,在Java编程中如果想调用C库,则必须通过JNI机制实现。这个实现的成本是很高的,因为两种不同语言的数据类型、调用约定完全不同,又牵涉到跨语言的异常传播和内存管理,不得不通过虚拟机进行昂贵的处理,效率十分低下。如果能够把两种语言都翻译到MapleIR,在IR上进行数据类型的融合,并在相当大程度上实现调用约定的统一,那么则可以极大的提高效率。我们把这个计划称为“拆墙行动” 。在拆墙行动基础之上,在我们长远的构思中是要做全程序优化的,这是一个跨语言的全程序优化,是对我们自己的巨大挑战。
显然,我们的理想不是做编译器,而是做软件开发系统。这是一个相当大的范围,可以理解为软件开发的生态。我们今天在做的每一件事情,包括Java静态编译,都是为这个目标做准备。它的未来已经着眼于建立完整的软件开发体系。在这整个生态中不得不提的就是编程语言和编程框架。软件开发人员看到的就是编程语言和相关框架,因此,这是生态的入口,方舟的未来必然在语言上要尝试,即使失败也要做。基于此,一个强大的具有相对自动适配能力的编译器前端是必须的。这个前端最大的特点必须是能够最大程度上的自动化,降低语言设计过程中的各种反复带来的开发成本。
除此之外,大量的基于一致的IR的开发工具,包括调试、调优等,必定会应运而生,为此,我们愿意和业界的共同爱好者一起努力,构建一个完整的方舟体系,在编程语言、编译、分布式异构编程框架、分布式运行系统等多个领域奠定基础。
最后推荐下这一优秀的系统,希望更多人加入openharmony的队伍共同丰富下生态。当前还不太完善,比如开发板太少,甚至没有旗舰版能跑完整openharmony3.0的全部功能。我觉得这是openharmony目前最大的痛点,但未来可期。
分布式:基于软总线的跨终端无缝体验
鸿蒙OS的“分布式OS架构”和“分布式软总线技术”通过公共通信平台、分布式数据管理、分布式能力调度和虚拟外设四大能力,使开发者能够聚焦自身业务逻辑,像开发同一终端一样开发跨终端分布式应用,也使最终消费者享受到强大的跨终端业务协同能力为各使用场景带来的无缝体验。
分布式软总线:
是多种终端设备的统一基座,为设备之间的互联互通提供了统一的分布式通信能力,能够快速发现并连接设备,高效地分发任务和传输数据。
引用:
TypeScript中文网 · TypeScript——JavaScript的超集
鸿蒙OS:万物互联,方舟Compiler - 吴建明wujianming - 博客园