WebAssembly入门
这是一篇关于WebAssembly简要介绍的文章,文章里不会涉及太多有关底层实现的细节,因为我也是刚开始接触这个领域。
后面如果进一步深入接触的话,可能会考虑出一系列后续文章。
这篇文章将主要分成三个部分:
- WebAssembly是什么
- WebAssembly可以解决什么问题
- 我们如何有效地使用它
素材的来源不仅限于官方文档,还有YouTube上一些精彩的分享,这些都列在尾部的参考中。
1. WebAssembly是什么
按照官网的说法,
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.
首先,它是个二进制指令格式,其次是基于栈的虚拟机,同时为多种不同编程语言生成可移植目标,而且可以在客户端和服务端上部署。
看起来很像是结合了Native的效率和Web的通用性。
特性主要有四个:
- 性能和速度
- 安全
- 开放和可调试
- 开放web平台的一部分
简而言之,WebAssembly的产生,就是为了将一些Native才有的能力,比如已有的稳定的库,原生应用的性能等,移植到Web上。
想想看,如果未来,所有的原生应用消失,我们所有的需求都可以通过一个浏览器满足,还是挺方便的。
2. WebAssembly的发展史
任何技术都不是无缘无故发生的。
WebAssembly的诞生,是为了解决JavaScript既有的一些问题。
V8引擎在2008年的时候被首次引入到Chrome,利用**即时编译(Just-in-time Compilation, JIT)**等技术,极大提高了JavaScript这门脚本语言的执行效率。Web因此可以更快、更好地做一些以前做不到的事。
但人的野心是无限的。
有人就想,能不能让JavaScript以一种类似Native code的效率运行?
于是Native Client (NaCI)的技术于2008年被Google的Brad Chen, Bennet Yee和David Sehr提出。后来为了可移植,又搞出了Portable Native Client (PNaCI)。基本的原理可见下图,因为NaCI本身就是个比较复杂的技术,这里不展开。
简单来说,NaCI有自己的runtime,运行在独立的进程中,通过一系列接口和外界交互。

asm.js和Emscripten则是走了另外一条路子。
直接将C++等Native语言,编译成js。其中,asm.js是一种低级的js的子集,目的是提供高性能的运行时环境;Emscripten则是一个工具链,将C/C++等代码编译成asm.js。

根据当时的测试,性能提升十分明显。

看起来已经很好了,但是还不够。
首先,相比于紧凑的二进制格式,asm.js需要解析,而解析需要时间,因此asm.js存在冷启动的问题;另外,asm.js仍然是一个比较hack的解决方案,可以解决部分问题,但并不通用。
于是在2015年,WebAssembly诞生了。
像是结合了NaCI和asm.js两者的有点。
一方面,它很像NaCI,不是基于js,而是一个全新的、经过正确设计、同时以二进制编码的指令集合。
另一方面,它又很像asm.js,和DOM运行在同一个进程里。
工具链主要有俩:
- Emscripten,只是编译产出结果是WebAssembly
- 一个新的LLVM WebAssembly后端,可以这么理解,LLVM将所有的语言都编译成一个中间语言(LLVM IR),后端要做的,就是将LLVM IR转换成另一门语言,这里是WebAssembly
WebAssembly仍然在发展,目标是将更多Native的能力搬到Web上,所以我们现在,可以借助WebAssembly,去做一些之前想做,但难以做到的事情了!
3. 如何开始
先看一个简单的例子。
假如我们有一个用C/C++写的模块,经过一系列处理,就可以在浏览器中实现调用。
我用的是Ubuntu系统。
先安装emcc
环境。
hello.cc
内容为:
#include <iostream>
int main() {
std::cout << "hello world" << std::endl;
return 0;
}
使用emcc
编译:
$ emcc hello.cc -o hello.html
也可以:
emcc hello.cc -o hello.{js/wasm}
其中:
wasm
是二进制的Wasm模块js
是一个包含胶水层的JavaScript文件,将原生的函翻译成js函数html
可理解为一个测试用的网页,实例化Wasm代码,然后展示结果
4. 总结
本文只是简单介绍了WebAssembly技术产生的背景,以及发展过程。最后提供了一个简单的example可以测试。
从某些方面上来说,WebAssembly并没有什么黑魔法,它只是将代码以一种更容易被优化的方式呈现,峰值的性能和原始js差不多。只不过原始的js,很难以一种优化的方式运行,而WebAssembly可以。
(完)
参考
- 本文作者: Plantree
- 本文链接: https://plantree.me/blog/2023/introduction-to-webassembly
- 版权声明: 本作品采用 知识共享署名 4.0 国际许可协议 进行许可,转载时请注明原文链接