一文带你探秘WebAssembly

304 阅读5分钟

什么是WebAssembly

WebAssembly(简称 Wasm)是一种高效的二进制指令格式,旨在为 Web 提供接近原生性能的运行环境。它被设计为一种可移植的目标语言,允许开发者用多种编程语言(如 C、C++、Rust 等)编写代码,并将其编译为可以在浏览器中高效运行的二进制格式。 image.png

image.png image.png

这上面是在Wasm出来之前的进化流程,最早的时候是由谷歌推出了早期的 NaCl(Native Client),下面我来讲解一下上面的图片

1. NaCl(Native Client)

  • 推出者:谷歌

  • 时间:2009年左右

  • 特点

    • NaCl 是谷歌最早推出的实验性技术之一,旨在允许 Web 应用运行接近原生性能的代码。
    • 它允许开发者将 C/C++ 编写的代码编译为一种特殊的二进制格式,并在浏览器中安全地运行。
    • 提供了对硬件加速的支持,但兼容性较低,仅限于特定平台和浏览器(如 Chrome)。
  • 问题

    • 兼容性差:其他浏览器厂商没有广泛支持。
    • 安全模型复杂:需要复杂的沙箱机制来保证安全性。

2. PNaCl(Portable Native Client)

  • 推出者:谷歌

  • 时间:2012年左右

  • 特点

    • PNaCl 是 NaCl 的改进版本,目标是提高跨平台兼容性。
    • 使用 LLVM 中间表示(IR)作为编译目标,生成可移植的二进制文件。
  • 问题

    • 虽然解决了部分兼容性问题,但仍未被广泛接受。
    • 生态系统较小,开发者采用率低。

3. asm.js

  • 推出者:Mozilla

  • 时间:2013年

  • 特点

    • asm.js 是一种 JavaScript 的严格子集,专为高性能应用设计。
    • 它通过优化 JavaScript 引擎(如 SpiderMonkey 和 V8)来实现接近原生的性能。
    • 可以通过 Emscripten 工具链将 C/C++ 代码编译为 asm.js。
  • 问题

    • 仍然是基于 JavaScript 的解释执行,性能受限于 JS 引擎的优化能力。
    • 需要依赖特定的优化技术,兼容性和性能表现因浏览器而异。

4. WebAssembly (Wasm) 的诞生

  • 时间:2015年开始标准化,2017年 MVP 版本发布

  • 特点

    • Wasm 是一个独立于 JavaScript 的二进制指令格式,旨在成为 Web 平台上的通用编译目标。
    • 支持多种编程语言(如 C、C++、Rust 等)编译为 Wasm。
    • 性能接近原生代码,同时具有良好的安全性、可移植性和兼容性。
    • 得到了主流浏览器厂商(Google、Mozilla、Microsoft、Apple)的共同支持。
  • 优势

    • 解决了 NaCl 和 asm.js 的兼容性问题。
    • 提供了一个开放的标准,推动了更广泛的生态系统发展。

在 Wasm 出现之前,NaCl 和 asm.js 是两个重要的先行者,但它们各自存在局限性:

  • NaCl 的兼容性较差,限制了其广泛应用。
  • asm.js 虽然提升了性能,但仍然受限于 JavaScript 的运行环境。

WebAssembly 的成功在于它吸取了这些早期尝试的经验教训,提供了一个更加高效、安全且跨平台的解决方案,最终成为现代 Web 开发的重要组成部分。

我们为什么需要WASM

WebAssembly 的优势

  • 更快的加载和执行速度:Wasm 的二进制格式比 JavaScript 更紧凑,解析速度更快。
  • 适合计算密集型任务:对于复杂的数学运算、图像处理、游戏开发等场景,Wasm 提供了显著的性能提升。
  • 安全性和隔离性:Wasm 运行在一个沙盒环境中,确保安全性。

提醒一个点: 与 JavaScript 协同工作:Wasm 并不是用来取代 JavaScript 的,而是作为补充。你可以通过 JavaScript 调用 Wasm 模块,也可以从 Wasm 中调用 JavaScript。

 如何在前端使用 WebAssembly

要使用 WebAssembly,你需要:

  1. 编写源代码:用 C、C++ 或 Rust 等语言编写代码。
  2. 编译为 Wasm:使用工具(如 Emscripten 或 Rust 的 wasm32 目标)将代码编译为 .wasm 文件。
  3. 加载和运行 Wasm:通过 JavaScript 加载 .wasm 文件并在浏览器中运行。

示例代码(JavaScript 调用 Wasm):

// 加载并实例化 Wasm 模块
WebAssembly.instantiateStreaming(fetch('example.wasm'), importObject)
  .then(obj => {
    const exports = obj.instance.exports;
    console.log(exports.add(1, 2)); // 假设 Wasm 模块导出了一个 add 函数
  });

下面是三段WASM法则

前端开发者需要掌握的内容

  • 基本原理:了解 Wasm 的设计理念及其与 JavaScript 的关系。
  • 工具链:熟悉如何使用工具(如 Emscripten、Rust 工具链)生成 Wasm 模块。
  • 内存管理:Wasm 使用线性内存(Linear Memory),需要手动管理内存分配和释放。

WebAssembly 使用线性内存来存储数据,所有的变量和数组都位于一个连续的内存区域中。我们可以通过 JavaScript 创建 WebAssembly.Memory 对象并与 Wasm 共享内存。需要注意的是,Wasm 不像 JavaScript 那样有垃圾回收机制,因此内存分配和释放需要手动管理。

  • API 使用:掌握如何通过 JavaScript 调用 Wasm 函数,以及如何传递参数和返回值。
  • 调试和优化:学习如何调试 Wasm 模块,并优化其性能。

 实际应用场景

  • 游戏开发:利用 Wasm 的高性能运行复杂的游戏逻辑。
  • 多媒体处理:用于音频、视频编码/解码或图像处理。
  • 机器学习:TensorFlow.js 和 ONNX Runtime 等库利用 Wasm 提升模型推理速度。
  • 桌面应用移植:将现有的桌面应用移植到 Web 上运行。

未来趋势

  • 更广泛的生态系统:越来越多的工具和框架开始支持 Wasm。
  • 服务端支持:除了浏览器,Wasm 还可以运行在 Node.js 和其他服务器环境中。
  • 标准化进展:随着 Wasm 标准的演进,更多高级特性(如多线程、SIMD 指令集)会被引入。

END

总之,WebAssembly 是现代前端开发的一个重要补充技术。虽然它不会完全取代 JavaScript,但在特定场景下,它可以显著提升应用的性能和功能。如果掘友们是高性能前端开发,建议深入学习 WebAssembly 的相关知识和实践。