一、介绍
WebAssembly(wasm)是一种简单的机器模型和可执行格式,具有广泛的规范。它被设计为可移植、紧凑,并能以接近本地代码的速度执行。
WebAssembly 由两种格式组成,它们表达相同的结构,但方式不同:
.wat文本格式(WebAssembly Text,简称 wat):使用 S 表达式,类似于 Lisp 家族的语言,如 Scheme 和 Clojure。.wasm二进制格式:低级别格式,供 wasm 虚拟机直接解析,概念上类似于 ELF 和 Mach-O。
示例:以下是一个使用 wat 编写的阶乘函数:
(module
(func $fac (param f64) (result f64)
local.get 0
f64.const 1
f64.lt
if (result f64)
f64.const 1
else
local.get 0
local.get 0
f64.const 1
f64.sub
call $fac
f64.mul
end)
(export "fac" (func $fac)))
如果你想看看 .wasm 文件的实际样子,可以使用 wat2wasm 进行转换。
二、线性内存模型
WebAssembly 具有非常简单的内存模型。一个 wasm 模块只能访问一块“线性内存”(linear memory),本质上是一个扁平的字节数组。该内存可以按照 64K 页的倍数增长,但无法缩小。
三、WebAssembly 仅适用于 Web 吗?
虽然 WebAssembly 目前主要应用于 JavaScript 和 Web 相关的场景,但它本身并不依赖于特定的宿主环境。因此,WebAssembly 未来很可能会发展为一种通用的“可移植可执行格式”,适用于各种不同的环境。目前,WebAssembly 主要与 JavaScript 生态系统结合使用,包括 Web 和 Node.js。
四、低级控制与高级体验
在 Web 应用开发中,JavaScript 虽然灵活,但往往难以保证稳定的性能。其动态类型系统和垃圾回收(GC)机制会导致性能波动,甚至在不经意间因偏离 JIT(即时编译器)的最佳路径而产生严重的性能回退。
Rust 提供了低级控制和可靠的高性能。由于 Rust 没有 GC 机制,因此不会遇到 JavaScript 常见的非确定性暂停问题。此外,Rust 允许开发者对间接访问、单态化(monomorphization)和内存布局进行精细控制,从而实现高效的代码执行。
五、小巧的 .wasm 体积
在 Web 应用中,代码体积至关重要,因为 WebAssembly(.wasm 文件)需要通过网络下载。Rust 没有运行时(runtime),因此生成的 .wasm 代码不会附带额外的垃圾回收器等不必要的负担。Rust 采用“按需付费”模式,仅包含实际使用的函数,最大程度地减少 .wasm 文件的大小。
六、无需推倒重来
采用 Rust 和 WebAssembly 并不意味着要完全抛弃现有的 JavaScript 代码。相反,开发者可以从性能最敏感的 JavaScript 代码入手,逐步迁移到 Rust,从而立即获得性能提升。更重要的是,如果只是优化特定的关键代码片段,也无需完全迁移整个代码库。
七、良好的生态兼容性
Rust 和 WebAssembly 可以无缝集成到现有的 JavaScript 生态系统中。例如,它支持 ECMAScript 模块(ESM),可以继续使用熟悉的工具链,如 npm 和 Webpack。这使得前端开发者能够更轻松地将 Rust 纳入他们的工作流程。
八、现代开发体验
Rust 还提供了现代开发者期望的各种便利功能,例如:
- 强大的包管理:借助 Cargo,Rust 的包管理工具,开发者可以轻松管理依赖和构建过程。
- 零成本抽象:Rust 允许开发者使用高级抽象而不会引入额外的运行时开销,从而兼顾可读性和性能。