导读:
高级语言虚拟机技术是每一位立志成为“高手”的程序员所必须修炼的“内功”。现今流行的编程语言当中,有许多都是基于虚拟机技术实现的,例如Java、JavaScript、PHP、Python、Ruby、Lua等等。前面提到的这些语言当中,目前最为火热的非JavaScript莫属了。
我们都知道,JavaScript是一门”先天不足“的语言,Brendan Eich在十天之内便设计和实现出了JavaScript原型。虽然带着各种缺陷问世,但JavaScript语言还是一路成长,最终成为了Web浏览器编程语言中的王者。
然而JavaScript毕竟是动态语言,无论浏览器如何进行优化也很难使其接近本地语言的执行速度。为了解决这一问题,WebAssembly(后文简称Wasm)技术应运而生。
目前WebAssembly正式版已经发布,并且得到了四大主流浏览器的一致支持。由于其开放和良好的设计,Wasm也很快获得了开源届的拥抱,各种主流编程语言已经可以编译为Wasm,此外还涌现出了各种实现和工具。在浏览器之外,Wasm首先在区块链领域获得了认可和应用。
和很多其他项目(比如Go和Rust语言)一样,Wasm也起源于业余时间项目。
2010年,Alon Zakai放弃了他自己的创业公司,加入Mozilla从事安卓版Firefox相关工作。
此时的Alon想把他以前开发的游戏引擎移植到浏览器上运行,他认为JavaScript或许已经足够快了,值得一试,所以开始在业余时间编写编译器,把C++代码(通过LLVM IR)编译成JavaScript。这个业余时间项目就是Emscripten。
到了2011年底,Emscripten项目已经取得了很大进展,甚至能够成功编译Python和Doom等大型C++项目。Mozilla觉得这个项目很有前途,于是邀请Alon加入了研究团队并全职开发Emscripten。
如前文所述,由于JavaScript语言太灵活了,所以JIT编译器很难做一些激进的优化。为了帮助编译器做这些优化,Alon和Luke Wagner,David Herman等人一起,在2013年提出了asm.js规范。
asm.js是JavaScript语言的一个严格子集,试图通过减少动态特性和添加类型提示来帮助浏览器提升JavaScript优化空间。相较于完整的JavaScript语言,裁剪后的asm.js更靠近底层,更适合作为编译器目标语言。
下面是用asm.js编写的一个简单例子:
functionMyAsmModule() {
"use asm";// 告诉浏览器这是一个asm.js模块
functionadd(x, y) {
x = x|0; // x是整数,
y = y|0; // y也是整数,
return (x+y)|0;// 返回值也是整数
} return { add: add };
}
从上面这个例子不难看出,asm.js有优点也有缺点。
优点非常明显:asm.js就是JavaScript,因此完全跨平台。“聪明”的浏览器可以根据提示进行激进的JIT优化,甚至是AOT编译,大幅提升性能。“笨”浏览器也可以视而不见,直接按普通JavaScript来执行,也没啥损失。缺点也很明显:”底层“的不够彻底。
比如说仍然是文本格式,要受JavaScript语法限制,浏览器仍然需要解析脚本、解释执行、收集性能指标、JIT编译等一系列步骤。
如果采用像Java类文件那样的二进制格式,不仅能缩小文件体积,减少网络传输时间和解析时间,还能选用更接近机器的字节码,这样AOT/JIT编译器实现起来会更轻松,效果也更好。
差不多在Alon和Mozilla尝试Emscripten/asm.js的同时,Google的Chrome团队也在试图弥补JavaScript性能问题,但方向有所不同。Chrome给出的方案是NaCl(Google Native Client)和PNaCl(Portable NaCl)。
限于篇幅的原因,这里就不详细介绍NaCl了。简而言之,通过NaCl,Chrome浏览器可以在沙箱环境中直接执行本地代码。asm.js和NaCl技术各有优缺点,二者其实没必要直接竞争,而是可以取长补短。Mozilla和Google也看到了这一点,所以从2013年开始,两个团队就经常交流和合作。
在交流的过程中,结合两个项目的长处、合作开发一种基于字节码的技术成了两个团队自然的选择。到了2015年4月左右,想法已经成熟,“WebAssembly”也取代其他临时名称,出现在两个团队的沟通邮件中。2015年7月,Wasm首次对外公开,并正式开始设计。同年,W3C成立了Wasm社区小组(成员包括Chrome、Edge、Firefox和WebKit),致力于推动Wasm技术的早期发展。
2017年2月底,Wasm社区小组达成共识,Wasm的MVP(Minimum Viable Product)设计基本定稿。同年3月底,Google决定放弃PNaCl技术,推荐使用Wasm。Mozilla基本上也放弃了asm.js技术,Emscripten可能会在未来停止对于asm.js的支持,仅支持Wasm。
除了四大浏览器的一致支持,Wasm也获得了主流编程语言的强力支持。C/C++是最先可以编译为Wasm的语言,因为Emscripten已经支持asm.js,只要把asm.js编译成Wasm即可。由于两项技术比较相似,这个工作并不难。2016年12月,Rust 1.14发布,开始实验性支持Wasm。2018年8月,Go 1.11发布,开始实验性支持Wasm。2019年3月,LLVM 8.0.0发布,正式支持Wasm。同年10月,Emscripten改为默认使用LLVM提供的Wasm编译后端直接生成Wasm。还有其他很多语言也都正式或通过第三方开源项目支持Wasm,由于篇幅的限制,这里就不一一列举了。
虽然诞生于Web和浏览器,但是Wasm并没有和Web或者浏览器绑定。相反,Wasm核心规范很少提及Web和浏览器(有单独的规范定Web和JavaScript API,详见后文)。这就给Wasm未来的应用前景提供了更加广阔的想象空间。在浏览器之外,可能首先被Wasm吸引的就是区块链项目。目前已经有一些区块链基于Wasm技术来实现智能合约平台,比如EOS。
著名的以太坊项目也正在将其虚拟机(Ethereum Virtual Machine,简称EVM)切换到Wasm,计划在以太坊2.0正式启用。开源世界对于Wasm技术的热情非常之高,目前已经有许多高质量的开源Wasm实现,包括用C/C++、Rust、Go等语言实现的Wasm解释器、AOT/JIT编译器。Wasm技术可谓前途一片光明。
以上内容摘自《WebAssembly原理与核心技术》
张秀宏 著
本书将对WebAssembly技术进行深入剖析。通过阅读本书,您不仅可以全方位了解WebAssembly核心技术,还可以在实战中学习如何设计并实现WebAssembly虚拟机和解释器。
本书共分为四部分,其中
第一部分将对WebAssembly技术进行简要介绍,
第二部分将详细介绍WebAssembly二进制和文本格式,
第三部分将详细介绍WebAssembly虚拟机和指令集,
第四部分将介绍高级语言支持、AOT编译、改进提案等进阶主题。
希望本书能够帮助你掌握WebAssembly核心技术,提前布局未来。
更多精彩回顾
资讯 |DB-Engines 10月数据库排名:“三大王”无人能敌,PostgreSQL紧随其后
上新 | 百度官方出品 | 全面解读PaddlePaddle,零基础快速入门深度学习
书单 | 开学季——计算机专业学生必读的10本畅销经典
视频 | 大佬出镜推荐不可不读系列——程序员陈彼得
点击阅读全文购买