3分钟了解 WebAssembly

虞修平
2023-12-01

一、概念

WebAssembly 官网的定义:

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

翻译为中文:WebAssembly(缩写 Wasm)是基于堆栈虚拟机的二进制指令格式。Wasm 是为了一个可移植的目标而设计的,可用于编译 C/ C+ / RUST 等高级语言,使客户端和服务器应用程序能够在 Web 上部署。

2012 年,Mozilla 的工程师 Alon Zakai 在研究 LLVM 编译器时突发奇想:许多 3D 游戏都是用 C / C++ 语言写的,如果能将 C / C++ 语言编译成 JavaScript 代码,它们不就能在浏览器里运行了吗?

Google开发了 Portable Native Client,是一种能让浏览器运行 C/C++ 代码的技术。 后来有了更高的追求。Google, Microsoft, Mozilla, Apple 等几家大公司一起合作开发了一个面向 Web 的通用二进制和文本格式的项目,那就是WebAssembly。

没错,WebAssembly 就是一种非 JavaScript 语言编写的代码也能够在浏览器运行的技术方案。与 WebAssembly 类似的还有 asm.js。两者功能基本一致,就是转出来的代码不一样。asm.js 是文本,WebAssembly 是二进制字节码。

大多数程序员会选择使用 C 语言来编写 WebAssembly 模块,并将其编译成 .wasm文件。这些 .wasm文件并不能直接被浏览器识别,所以它们需要一种称被为 JavaScript 胶接代码(glue code,用于连接相互不兼容的软件组件)来加载。

二、WebAssembly 使用

编写 WebAssembly 所需的环境如下:

  1. 支持 WebAssembly 的浏览器,新版的 Chrome 或者 Firefox 均可。点此查看各浏览器对 WebAssembly 支持情况

  2. 由 C 到 WebAssembly 的编译器,一般使用 Emscripten。需要占用约 1GB 的硬盘空间。

  3. C 编译器/开发环境,比如 Linux 下的 GCC,OS X 下的 Xcode,Windows 下的 Visual Studio。

  4. 本地 web 服务器。Linux/OS X下使用 python -m SimpleHTTPServer 9000命令即可,Windows下可安装 IIS 服务。

.wasm 文件是 WebAssembly 组件,它可以被 JavaScript 加载,加载过程比较复杂。

functionfetchAndInstantiate(url,importObject){
	returnfetch(url).then(response =>
		response.arrayBuffer()
	).then(bytes =>
		WebAssembly.instantiate(bytes,importObject)
	).then(results =>
		results.instance
	);
}

WebAssembly 中的函数只能使用 WebAssembly 类型(整数或浮点数)作为参数或返回值。对于任何更复杂的数据类型(如字符串),必须使用 WebAssembly 模块的内存。

三、JavaScript 和 WebAssembly

在许多情况下,执行相同任务时 WebAssembly 将胜过 JavaScript 。原因如下:

(一)解析
JavaScript:需要通过浏览器中的 JavaScript 引擎翻译成机器可以识别的机器语言。在解析过程中,JavaScript 一旦被浏览器下载,就会被转换为 AST 语法树,然后 AST 再转换为字节码。

WebAssembly:
WebAssembly 不需要被转换,因为它已经是二进制字节码了,所以运行速度更快、体积更小。它仅仅需要被解码并确定没有任何错误。

(二)编译
JavaScript :在执行代码期间编译。JavaScript 是动态类型语言,相同的代码在多次执行中都有可能都因为代码里含有不同的类型数据被重新编译,这样会消耗时间。

WebAssembly:WebAssembly 与机器代码更接近。编译器不需要在运行代码时花费时间去观察代码中的数据类型,在开始编译时做优化。编译器不需要去关注每次执行相同代码中数据类型是否一样。

(三)执行
JavaScript :依靠 JIT 做优化。但是大部分开发者并不知道 JIT 的实现原理。即便知道为了让代码更易于阅读,也会阻碍编译器优化代码。
WebAssembly:为编译器设计的。专门给编译器来阅读,并不是当做编程语言让程序员去写的。不需要直接编程,所以 WebAssembly 提供了一组更适合机器的指令。根据您的代码所做的工作,这些指令的运行速度可以在10%到800%之间。

(四)垃圾回收
JavaScript :开发者不需要担心内存中无用变量的回收。JS 引擎使用垃圾回收器来自动进行垃圾回收处理。这对于控制性能可能并不是一件好事。你并不能控制垃圾回收时机,所以它可能在非常重要的时间去工作,从而影响性能。

WebAssembly:不支持垃圾回收。内存是手动管理的(就像 C/C++)。虽然这些可能让开发者编程更困难,但它的确提升了性能。

四、WebAssembly 现状

2018 年 2 月 28日,四大浏览器宣布达成共识,即 WebAssembly 的 MVP (最小化可行产品)已经完成。大约一周后,Firefox 会默认打开 WebAssembly 支持,而 Chrome 则在第二周开始。它也可用于预览版本的 Edge 和 Safari。

虽然 WebAssembly 还在发展初期,但从公布的新标准来看,其潜力巨大。在浏览器中运行低级语言的能力,将会带来全新的应用程序与 web 体验,这是仅靠 JavaScript 无法做到的。

但是目前使用 WebAssembly 还十分繁琐,文档需要分为多个部分,其配套的工具也不容易使用,并且还需要 JavaScript 胶接代码才能使用 wasm 模块。相信不远的将来,随着越来越多的人进入这个平台,这些问题都将会被逐一解决。

 类似资料: