WebAssembly入门

2023-09-19 pv

这是一篇简单介绍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这门脚本语言的执行效率。

但人的野心无限。

有人就想,能不能让JavaScript以一种类似Native code的效率运行?

于是Native Client (NaCI)🔗的技术于2008年被Google的Brad Chen, Bennet Yee和David Sehr提出。后来为了移植性,又搞出了Portable Native Client (PNaCI)。

基本的原理可见下图,由于NaCI本身就是个比较复杂的技术,这里不展开。

简单来说,NaCI有自己的runtime,运行在独立的进程中,通过一系列接口和外界交互。

asm.jsEmscripten则是走了另外一条路。

直接将C++等Native语言,编译成JavaScript。其中,asm.js是一种低级的JavaScript子集,目标是提高运行效率;Emscripten是一个工具链,将C/C++等代码编译成asm.js。

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

看起来已经很好了,但是还不够

因为首先,相比于紧凑的二进制格式,asm.js需要解析,解析就需要耗费时间,因此asm.js存在冷启动的问题;另外,asm.js仍然是一个比较hack的解决方案,只能解决部分问题。

于是在2015年,WebAssembly诞生。

结合了NaCI和asm.js两者的优点。

一方面,它很像NaCI,不是基于JavaScript,而是一个全新的、经过正确设计、同时以二进制编码的指令集合

另一方面,它又很像asm.js,运行在Render进程里。

工具链主要有两个:

  • Emscripten,但是编译产出结果是WebAssembly,而不是asm.js
  • 一个新的LLVM WebAssembly后端,可以这么理解,LLVM将所有的语言都编译成一个中间语言(LLVM IR),后端需要做的,就是将LLVM IR转换成另一门语言,这里是WebAssembly

尽管WebAssembly诞生还不到10年,仍然在发展,但最新的浏览器已经支持了很多新特性。

3. 如何开始

先看一个简单的例子。

假如我们有一个用C/C++写的模块,经过一系列处理,就可以实现在浏览器中调用。

测试用的是Ubuntu系统。

先安装emcc环境。

hello.cc内容为:

#include <iostream>
int main() {
std::cout << "hello world" << std::endl;
return 0;
}

使用emcc编译:

Terminal window
$ emcc hello.cc -o hello.html

也可以:

Terminal window
emcc hello.cc -o hello.{js/wasm}

其中:

  • wasm是二进制的Wasm模块
  • js是一个包含胶水层的JavaScript文件,将原生的函数翻译成js函数
  • html可理解为一个测试用网页,实例化Wasm代码,然后展示结果

4. 总结

本文只是简单介绍了WebAssembly技术产生的背景,以及发展过程,最后提供了一个简单的example供测试。

从某些方面看,WebAssembly并没有什么黑魔法,它只是将代码以一种更容易被优化的方式呈现,峰值的性能和原始JavaScript差异不大,只是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 上编辑本页面

最后更新于: 2024/03/04 06:51:47