你以为 Wasm 只能靠 JIT 跑出浏览器?今天 Rust 把它变成嵌入式解释器了

配了三年 WebAssembly,跑 WASM 这件事基本等于「浏览器 + V8/Wasmtime JIT」。但 2026 年 9 月 1 日发布的 Wasmi 2.0 告诉你:Wasm 还有另一条路——纯 Rust 实现的解释器,今天跑到 2.2 倍速。


这件事是什么

Wasmi 是一个用 Rust 写的 WebAssembly 解释器,不是 JIT 编译器。JIT 的逻辑是「跑的时候边编译边优化」,解释器的逻辑是「直接按指令一条条执行」——直观上 JIT 应该更快,但 Wasmi 2.0 证明了在嵌入式场景,解释器可以做得非常极致。

官方数据:在 Apple M2 Pro 上,Wasmi 2.0 相比 1.0 版本性能提升约 2.2 倍(几何平均值),benchmark 覆盖 wasmi-benchmarks 全量测试集。同时,Wasmi 2.0 超越了一众竞品:Wasm3、WAMR fast-interpreter、Wasmtime Pulley、Makepad Stitch,成为当前最快的便携式 Wasm 解释器。


它怎么做到的:五项工程改造

这不是靠「优化参数」调出来的,是重写了解释器核心架构。五项核心技术:

1. 直接线程化代码(Direct-Threaded Code)

这是解释器性能的核心开关。传统解释器用「跳转表」dispatch 每条指令:取指令 → 解码 → 跳到处理函数 → 返回 → 取下一条。直接线程化把每条指令的处理函数直接「粘」在一起,用尾调用跳转,省掉循环开销。

Wasmi 2.0 提供四种 dispatch 模式:超越直接线程化、直接线程化、中断直接线程化、开关分派。不同模式权衡冷启动速度与峰值性能,前端工程师不需要理解细节,wasm-pack build 出的 wasm32-unknown-unknown 目标文件直接塞进去就能用。

2. 累加器寄存器

传统 WASM 解释器基于栈操作:每次运算要把值 push 到栈、pop 出来、计算、再 push 回去,每条指令至少两次内存访问。

Wasmi 2.0 引入了累加器寄存器——一个类似 CPU 寄存器的变量,承载当前操作结果。大部分指令直接操作累加器,避免反复访问栈内存,开销从「两次内存操作」变成「一次寄存器操作」。

3. 实例访问优化

WASM 模块有内存(Memory)、全局变量(Global)、表(Table)等实例对象。1.0 版本访问这些对象需要一层间接查找,2.0 重构了 InstanceEntity 布局,把高频访问的字段放在一起,让内存和全局变量的读写几乎零开销。

4. 无锁 CodeMap

函数调用管理是解释器的另一个瓶颈。Wasmi 2.0 用 lock-free 数据结构做函数映射(CodeMap),支持并发低开销的函数调用。对单线程场景也有收益——无锁实现避免了锁的内存屏障开销。

5. 编译器优化修复

这一项很有意思:Rust 编译器本身有个「反优化」bug,与分支预测相关,特定 pattern 导致生成的机器码性能反而下降。Wasmi 团队识别并绕过了这个坑,让 Rust 编译器真正发挥出 LLVM 后端的能力,条件指令性能大幅提升。


和你以前认识的 Wasm 不一样

这里有个认知需要刷新:浏览器 Wasm 和嵌入式 Wasm 是两个完全不同的需求。

浏览器里跑 Wasm:V8/LlamaVM 的 JIT 编译发挥峰值性能,但冷启动有编译开销,不适合「几十毫秒内要跑完」的短任务。

嵌入式跑 Wasm(IoT 设备、插件沙盒、智能合约、游戏脚本):没有 JIT、也没有长时间预热,解释器冷启动必须快,每条指令执行必须稳定可预期。

场景对应

场景 代表项目 核心诉求
浏览器 Figma/AutoCAD web 版 峰值性能,冷启动容忍
智能合约 Soroban / Ripple 确定执行成本,防无限循环
插件沙盒 Typst / Zellij / Josh 安全隔离,快速加载
IoT Firefly Zero 游戏机 极低资源占用

Wasmi 2.0 在所有这些场景都有直接价值,而且性能已经超过了多数 JIT 实现。


三件新增能力

性能提升之外,Wasmi 2.0 还补齐了三个生产级功能:

稳定燃料计量(Fuel Metering):WASM 执行可以按燃料(fuel)计费,每消耗一定计算量就触发中断。智能合约场景这是必须的——没有燃料计量,就没有办法防止无限循环消耗 gas。Wasmi 2.0 把这个做稳定了。

确定性 Profile 支持:WASM 有一个 deterministic profile,专门给需要跨平台结果完全一致的场景。Wasmi 2.0 现在正式支持这个 profile。

validate crate:把 Wasmi 验证器单独打包成 crate,嵌入到其他项目时二进制体积显著减小。


前端工程师什么时候用它

大多数场景你还是用 wasm-pack + wasm-bindgen,那套走的是 WASI/JIT 路线,是主流。

但如果你在做一个插件系统,想让用户上传 WASM 模块在服务端安全执行——Wasmi 比 Wasmtime 更轻量,比 Deno 更可控。

如果你在考虑边缘计算,想把 WASM 模块推到 CDN 边缘节点执行——解释器的确定性执行时间和零冷启动开销是有意义的。

如果你在做编辑器或设计工具,想让第三方开发者写插件——Typst 已经这么做了一年多了,Wasmi 是目前生产验证最充分的方案。


下一步

想跑起来?三行命令:

“`bash
cargo add wasmi

或者用 CLI 直接跑 wasm 文件

cargo install wasmi_cli
wasmi run your_module.wasm
“`

Rust 项目嵌入 Wasmi:

“`toml

Cargo.toml

[dependencies]
wasmi = “2.0”
“`

“`rust
use wasmi::{Engine, Linker, Module, Store};

fn main() {
let engine = Engine::default();
// 加载 wasm 模块
}
“`


总结一句话:Wasmi 2.0 把「Rust 解释器 + WebAssembly」这条路的性能天花板从「能用」拉到了「领先」,嵌入式和合约场景有了生产级选择,前端工具链里这块拼图补完了。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 15 阅读