快速认识 WebAssembly

快速认识 WebAssembly

WebAssembly 即 Wasm 就像浏览器运行时的一种高效的低级编程语言,它可以将高级语言编译成二进制格式,并在WEB上运行它们,而不需要浏览器或插件。

为什么需要WebAssembly

尽管现代 JavaScript 是一种相当快的语言,但它是不可预测的,执行也不一致。而且,它不是一个好的编译目标。实用插件对于用户体验相当不友好且不可行,诸如 ElmDart 等新语言来编译脚本语言。谷歌和Mozilla创建了Native Clientasm.js 来满足复杂应用的需求。然而,所有这些尝试都未能解决WEB上安全快速代码的问题。

WebAssembly 最早是在2015年由 JavaScript 的创造者Brendan Eich提出的。继JavaScript之后,它是第一种得到普遍支持的语言。万维网联盟(W3C)在2017年开发了WebAssembly,当时的目标:

  • 快速,高效和平台:它使用常见的硬件功能在不同的平台上执行接近本机的代码性能。紧凑的代码可以在一次传递中被解码、验证和编译,与即时或提前编译一样。
  • 可读可调试:代码定义良好,便于检查和调试,程序可以被分解成可以独立工作的模块(更小的部分)。
  • 解码、验证和编译是可流式的(在看到所有数据之前开始)和可并行化(可以拆分为许多独立的并行任务)。
  • 不要破坏WEB,保持向后兼容性。

WebAssembly 定义

Wasm 是基于堆栈的虚拟机的二进制指令格式。 Wasm 被设计为可移植的目标,用于编译 C/C++Rust 等高级语言,支持在 Web 上部署客户端和服务器应用程序。

  • 二进制指令格式:文本格式的 WebAssembly 代码用于定义抽象语法树,它描述了程序的组件并简化了验证和编译。AST 被编译(使用 Emscripten SDK 等编译器)为二进制格式的 .wasm 文件,该文件被加载到网页中。浏览器的 JavaScript 引擎然后使用解码堆栈将文件解码回 AST 来解释它。
  • 用于编译的便携式目标:由于 WebAssembly 被设计为在虚拟机上运行;无论操作系统和指令集架构如何,它都可以在各种设备上运行。

WebAssembly 优势

WebAssembly 正在迅速成为一种主流技术,它被所有主要的浏览器供应商采用,特别是因为接近原生的代码性能。除此之外 WebAssembly 还拥有以下优势:

  • 更好的性能:WebAssembly 在两个方面提供了增强的性能,即启动速度和吞吐量。缩小的 JavaScript 需要被解析、解释、编译和优化。另一方面,wasm 更紧凑,并且由于其简洁的设计,二进制格式允许更快的解析和快速优化。
  • 便携且安全:它独立于平台、独立于硬件和独立于语言,它不对设备或浏览器没有任何特殊要求,这增强了其便携性,代码在内存安全的沙盒环境中进行验证和执行,可以防止安全漏洞和数据损坏。
  • 集成遗留库:如果应用程序使用 C/C++ 或任何其他兼容语言,WebAssembly 可以轻松地将代码或桌面应用程序可用于 Web。通常使用两个库;用于 Rust 的wasm-pack 和用于 C/C++Emscripten

WebAssembly 应用场景

WebAssembly 通常用于需要高性能的计算密集型应用程序。这些包括元宇宙相关技术 AR/VR 实时开发、视频编辑、VPN、图像识别等。要了解学习 wasm 的各种技术,请单击此处

  • tensorflow.js 中加入 wasm 后端支持后,模型的性能提升了 10 倍左右。
  • 由于它最初是用 C++ 编写的,因此 Figma 使用 Emscripten 导出到 Asm.js,通过添加适当的 Emscripten 标志启动 WebAssembly 后,大概 3 倍的性能提升。
  • 切换到 WebAssembly 后,OpenCV Python 库的性能提升非常明显。 ResNet50 的推理时间增加了 15 倍,内核性能测试速度提高了 3.5 倍。
  • Unity 使用 Emscripten 输出 WebAssembly 为游戏导出网络播放器,传统上由于 JavaScript 速度变慢而无法导出到 Web 的游戏,在 Web 上获得了始终如一的良好性能。

在被浏览器广泛支持后,一些重量级的应用也逐渐移植到了Web上,包括:

  • Google Earth:一种主要基于卫星图像呈现地球 3D 表示的软件。
  • AutoCAD:计算机辅助设计和绘图软件应用程序,它是在带有内部图形控制器的微型计算机上运行的桌面应用程序。
  • TensorFlow:用于机器学习和人工智能的免费开源软件库。

WebAssembly 实现

根据所使用的语言,有四种方法可以在 Web 应用程序中实现 WebAssembly。

  • 使用 Emscripten 移植 C/C++ 应用程序。
  • 直接在程序集级别编写或生成 WebAssembly
  • 编写一个 Rust 应用程序并将 WebAssembly 作为其输出。
  • 使用编译为 WebAssembly 二进制文件的 AssemblyScript。

WebAssembly 实现

应用程序中嵌入 WebAssembly

如下图所示,无论是 Web 应用还是非 Web 应用,都需要在宿主程序中嵌入 WebAssembly 运行时才能使用 WebAssembly。唯一的区别是,在Web应用程序中,宿主程序是浏览器,而在非Web场景中,宿主程序是自己的应用程序,具体到本文所关注的后端应用程序,宿主程序是后端服务。

应用程序中嵌入 WebAssembly

目前可用的 WebAssembly 运行时包括 WasmtimeWasmEdgeWAVMWasmer 等,各有优缺点。

WebAssembly 局限性

虽然不断开发新功能,但 WebAssembly 的功能是有限的。

  • 没有垃圾收集:与采用垃圾回收的 JavaScript 不同,Wasm 使用平面/线性内存模型,在实例化时分配大量内存并且不会自动回收内存。
  • 不能直接访问DOM:WebAssembly 无法访问文档对象模型 (DOM),任何 DOM 操作都需要使用 JavaScript 间接完成。或者,在通过 JavaScript 胶水代码完成 DOM 操作的情况下,也可以使用任何工具链,例如 Emscripten。性能取决于所使用的库。
  • 旧浏览器不支持:通常较旧的浏览器没有可用于实例化和加载 Wasm 模块的所需对象。

浏览器WebAssembly支持程度