WebAssembly初探

328 阅读6分钟

WebAssembly背景

官网:webassembly.org/

image.png

  • 什么是 Wasm(WebAssembly的简写,下同):
    • 是一种基于堆栈的虚拟机的二进制指令格式。
    • 被设计为编程语言的可移植编译目标。
    • 能够在网络上部署客户端和服务器应用程序。

发展历史

最早 WebAssembly1.0 基于 asm.js(Javascript 的严格子集,静态类型,取消垃圾回收机制等)的特性集实现。随后的 WebAssembly2.0 又根据新的标准进行了进一步的延伸和开发。

WebAssembly 的开发团队分别来自 Mozilla、Google、Microsoft、Apple,代表着四大网络浏览器 Firefox、Chrome、Microsoft Edge、Safari。

重要的时间线(倒序)

  • 2022 年 6 月,开始发布 WebAssembly 2.0。
  • 2019 年,Chrome 75 发布,默认启用 WebAssembly 线程。
  • 2018 年 2 月,WebAssembly 工作组(WebAssembly Working Group)发布了核心规范、JavaScript 接口和 Web API 的三个公开工作草案。
  • 2017 年 3 月,首次发布 WebAssembly MVP 版本,预览版本结束,正式进行发布,可以理解为 1.0。
  • 2015 年 WebAssembly 首次发布,在上述四大浏览器中进行了 Unity 的 Angry Bots(愤怒的机器人)的演示。

1.0 和 2.0 区别

  • 1.0 主要目标是在所有主要浏览器中能运行 WebAssembly。根据统一截至 2022 年 10 月 ,96% 的已安装浏览器支持 WebAssembly(1.0 版),基本实现了全覆盖。
  • 让 WebAssembly 焕发第二春(2.0)的:可以借助 WASI(WebAssembly System Interfac) 的模块化系统接口,能够借此中间产物 .wasm 实现各语言的集合和互相集成。

总结: WebAssembly 2.0 起,边界更大了,目标完全就是可移植、安全的高级语言。期望应用于浏览器、各编程语言、各系统中。

WebAssembly架构

image.png

和JavaScript对比

  • 预编译:WebAssembly代码是预编译的,这意味着它不需要在运行时进行解释或编译,而是直接在浏览器中运行原生机器代码。而JavaScript需要在运行时解释和编译,这会导致一些性能损失。

  • 更小的代码:WebAssembly二进制文件比JavaScript文件更小,因为它是一种低级别的虚拟机代码,不需要包含大量的文本和元数据,这减少了下载时间和解析时间。

  • 更少的内存使用:WebAssembly可以使用更少的内存来执行相同的任务。这是因为WebAssembly代码是编译为本机机器码,它可以更好地利用内存,避免了一些JavaScript中的垃圾回收和内存分配开销。

  • 更好的硬件加速支持:WebAssembly支持更好的硬件加速,如SIMD(单指令多数据)和GPU(图形处理单元)加速,这使得它可以在执行一些计算密集型任务时更快速地运行。

与Service Workers和 Web Workers的区别

Service Workers 还有 Web Workers 允许应用在后台运行,也可以做到离线运行和缓存。它们模仿线程,无法访问DOM,并且不能共享数据(仅能通过消息传递),只能在单独的上下文中运行。但其实我们甚至可以在其中运行 WASM 而不是 JS。对我来说,它们只提供一些具有特殊特权的抽象层,没有人说这些层必须执行 JS。

Service Workers 还有 Web Workers 是浏览器上的功能,不是 JS 的专有功能。

应用场景

这些应用共同特点是,它们通常会被看作是桌面应用。通过为 CPU 密集型任务提供接近本机的性能,WebAssembly 使得将这些程序迁移至 Web 成为可行。

  • 游戏

2015年,Unity Technologies推出了一款演示游戏Angry Bots,它是一款基于WebAssembly的游戏,旨在展示Unity游戏引擎在WebAssembly上的性能和可用性。

未来,随着WebAssembly技术的不断发展和完善,Web游戏的性能和可用性将会得到更大的提升,为玩家带来更加丰富和精彩的游戏体验。

  • 科学的可视化和模拟
    (待续)

  • CAD应用
    (待续)

  • 图像/视频编辑
    (待续)

工具介绍

C/C++ 和 Rust 语言提供了多种工具,如 Emscripten、wasi-sdk、wasm-pack 和 wasm-bindgen 等,可根据不同的应用场景实现 WebAssembly 的编译和打包。

而 TinyGo 和 AssemblyScript 则分别提供了专为 Go 的 WebAssembly、嵌入式场景和 TypeScript 的变体语言开发的编译器。

还有两个通用工具 Binaryen 和 wabt。前者能够优化 WebAssembly 代码,后者提供常用的 WebAssembly 工具和格式转换功能;

除了 C/C++、Rust、GO这些后端开发语言对WebAssebly提供支持外,开源社区还推出的AssemblyScript, 它是是一个把 TypeScript 转换到 WebAssembly 的编译器。

AssemblyScript中文网

工具清单

- tinygo
TinyGo 是一个 Go 编译器,旨在用于微控制器,WebAssembly(WASM)和命令行工具等小型场景。它重用了 Go 语言工具和 LLVM 一起使用的库,以提供编译用 Go 编程语言编写的程序的另一种方法。 网址:tinygo.org/

- Binaryen
binaryen 是一款 WebAssembly 工具集,它可以用来优化、分析、编译和验证 WebAssembly 代码。本文将向您介绍如何使用 npm 包 binaryen,以及如何使用 binaryen 来优化您的 WebAssembly 代码。

- wabt
wabt 是一个工具链集合,其中包括 WebAssembly 的反汇编工具、解释器、编译器、验证工具等。下面简单对几个常用工具进行介绍。

- Emscripten
Emscripten: 是一个开源的编译器,该编译器可以将 C/C++ 的代码编译成JavaScript胶水代码。Emscripten可以将 C/C++ 代码编译为WebAssembly编程语言的代码。

** - wasi-sdk**
wasi-sdk: 可以看作是魔改过后的 LLVM,添加了 WASI 的支持。使用方式和 clang 编译 C/C++ 项目基本一致,可以直接使用 clang 命令。wasi-sdk 中,libc 的实现和 Emscripten 相似,都是使用了开源的 musl libc 库,进行了部分修改以适配 WASI。在 C/C++ 编写的 WebAssembly 工程中,可以使用 wasi-sdk 替代 LLVM 作为默认编译工具链。

- wasm-pack
wasm-pack: 工具由 Rust / WebAssembly 工作组开发维护,并且是现在最为活跃的 WebAssembly 应用开发工具。它支持将代码打包成 npm 模块,并且随附了 Webpack 插件,可以轻松地与已有的 JavaScript 应用结合。

- wasm-bindgen
wasm-bindgen 让 WebAssembly 模块和 JavaScript 之间能够进行交互。同样的 wasi-sdk 也存在和 Emscripten 相似的局限性,包括多线程、time 能力等都是缺失的。