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可以。

(完)

参考

  1. What is WebAssembly and where did it come from?
  2. History of WebAssembly (Chrome University 2019)
  3. WebAssembly for Web Developers (Google I/O ’19)
  4. WebAssembly官网
  5. Mozilla WebAssembly
在 GitHub 上编辑本页面 更新时间: 10/13/2023, 12:55:21 AM