WebAssembly是什么
WebAssembly 是一种新的字节码格式,主流浏览器都已经支持 WebAssembly。 和 JS 需要解释执行不同的是,WebAssembly 字节码和底层机器码很相似可快速装载运行,因此性能相对于 JS 解释执行大大提升。 也就是说 WebAssembly 并不是一门编程语言,而是一份字节码标准,需要用高级编程语言编译出字节码放到 WebAssembly 虚拟机中才能运行, 浏览器厂商需要做的就是根据 WebAssembly 规范实现虚拟机。
WebAssembly原理
要搞懂 WebAssembly 的原理,需要先搞懂计算机的运行原理。 电子计算机都是由电子元件组成,为了方便处理电子元件只存在开闭两种状态,对应着 0 和 1,也就是说计算机只认识 0 和 1,数据和逻辑都需要由 0 和 1 表示,也就是可以直接装载到计算机中运行的机器码。 机器码可读性极差,因此人们通过高级语言 C、C++、Rust、Go 等编写再编译成机器码。
由于不同的计算机 CPU 架构不同,机器码标准也有所差别,常见的 CPU 架构包括 x86、AMD64、ARM, 因此在由高级编程语言编译成可自行代码时需要指定目标架构。
WebAssembly 字节码是一种抹平了不同 CPU 架构的机器码,WebAssembly 字节码不能直接在任何一种 CPU 架构上运行, 但由于非常接近机器码,可以非常快的被翻译为对应架构的机器码,因此 WebAssembly 运行速度和机器码接近,这听上去非常像 Java 字节码。
相对于 JS,WebAssembly 有如下优点:
- 体积小:由于浏览器运行时只加载编译成的字节码,一样的逻辑比用字符串描述的 JS 文件体积要小很多;
- 加载快:由于文件体积小,再加上无需解释执行,WebAssembly 能更快的加载并实例化,减少运行前的等待时间;
- 兼容性问题少:WebAssembly 是非常底层的字节码规范,制订好后很少变动,就算以后发生变化,也只需在从高级语言编译成字节码过程中做兼容。可能出现兼容性问题的地方在于 JS 和 WebAssembly 桥接的 JS 接口。
每个高级语言都去实现源码到不同平台的机器码的转换工作是重复的,高级语言只需要生成底层虚拟机(LLVM)认识的中间语言(LLVM IR),LLVM 能实现:
- LLVM IR 到不同 CPU 架构机器码的生成;
- 机器码编译时性能和大小优化。
除此之外 LLVM 还实现了 LLVM IR 到 WebAssembly 字节码的编译功能,也就是说只要高级语言能转换成 LLVM IR,就能被编译成 WebAssembly 字节码,目前能编译成 WebAssembly 字节码的高级语言有:
- AssemblyScript:语法和 TypeScript 一致,对前端来说学习成本低,为前端编写 WebAssembly 最佳选择;
- c\c++:官方推荐的方式,详细使用见文档;
- Rust:语法复杂、学习成本高,对前端来说可能会不适应。详细使用见文档;
- Kotlin:语法和 Java、JS 相似,语言学习成本低,详细使用见文档;
- Golang:语法简单学习成本低。但对 WebAssembly 的支持还处于未正式发布阶段,详细使用见文档。
通常负责把高级语言翻译到 LLVM IR 的部分叫做编译器前端,把 LLVM IR 编译成各架构 CPU 对应机器码的部分叫做编译器后端; 现在越来越多的高级编程语言选择 LLVM 作为后端,高级语言只需专注于如何提供开发效率更高的语法同时保持翻译到 LLVM IR 的程序执行性能。
最新评论