
在这里,我们要谈论的引擎总是与某种语言绑定,也可称之为虚拟机。那么一个引擎如何驱动一段程序运行,并得到结果呢

wasmtime总体分为编译、运行和工具三部分

这一部分包含四个组件,从上到下分别是 wasm-environ wasm-cranelift wasm-jit wasm-obj
从内部视角来看,wasm-environ是编译的入口,但实际上wasm-cranelift会负责执行函数级别的即时编译,为每一个函数生成 JIT 代码。得到 JIT 代码之后,需要存储在可执行内存区域才能被实际执行,这一步依赖wasm-jit对引擎内部可执行内存的管理。另外,wasm-obj会根据编译过程中产生的各类信息,生成 ELF(Executable and Linkage Format)映像,其中包括所有的编译得到的函数以及跳板(Trampoline)函数、用于链接阶段的重定位记录等内容。如果 wasm 模块中存在 DWARF 信息,则会被写入对应模块 ELF 映像的.dwarf段
这部分主体是wasm-runtime,它将维护wasm模块在运行时的各类数据结构,为程序运行提供必要的支持。wasm-runtime组件负责维护两类重要的实体 Store和InstanceHandle
除了wasm-runtime外,运行时部分还存在组件wasm-fiber用于支持一部功能,主要处理栈的切换
wasm3是一款基于解释器执行的轻量级WebAssembly引擎,使用C语言开发,拥有比较完善的wasm运行时系统
wasm3的最大特点就是依靠纯解释器执行所有的WebAssembly指令,没有引入JIT/AOT编译。
这里有两个关键的设计
美中不足的是,目前 wasm3 对于社区标准规范的支持还有待完善,包括已被纳入核心规范的多线性内存、引用类型、异常处理等提案
与 wasmtime 一样,WasmEdge 也是一种编译型的 wasm 引擎,可以按照 JIT/AOT 两种模式对 wasm 指令进行编译,并最终执行。不同之处在于,WasmEdge 使用 LLVM 作为编译器后端,利用了 LLVM 出色的优化编译能力。因此,相比于使用 Cranelift 的 wasmtime,WasmEdge 生成的指令更优,执行速度更快
除了卓越的性能表现之外,WasmEdge 的一个最为显著的特点就是社区提供丰富的扩展能力。比如,在云原生的使用场景中,很多开发者使用 JavaScript 语言开发应用。为此,WasmEdge 以 wasm 模块形式(名为 wasmedge_quickjs.wasm)提供了 QuickJS 引擎能力, 以便在 wasm 环境中执行 JavaScript 代码。在此基础上,WasmEdge 社区提供了一揽子基于 JavaScript 的能力扩展
wasm-micro-runtime 也简称为 WAMR,与 wasmtime 一样是隶属于 Bytecode Alliance 的开源 WebAssembly 引擎项目,适用于嵌入式平台、各类 IoT 设备、智能合约和云原生等场景。名字中的 micro 也正是它的特点之一: WAMR 的二进制产物很轻量,纯 AOT 配置的产物体积只有约50KB,非常适合资源受限的宿主
与上述三款引擎只支持解释执行或编译后执行不同,WAMR 同步支持解释与编译两种方式执行 wasm 程序,因此兼有两种执行方式低冷启延迟、高峰值性能的优点。使用编译模式时,宿主可以选择使用 JIT 或 AOT 方式执行目标程序。与 WasmEdge 相同,WAMR 的编译器也基于 LLVM 构建。根据官方数据,JIT 或 AOT 的执行方式可以得到接近原生的速度,表现十分亮眼。而援引最新的2023年 wasm runtime 的性能测试数据,wamr 是运行速度最快的引擎
| 引擎 | 关键特性 | 介绍 |
|---|---|---|
| wasmtime | 高性能编译 字节码联盟项目 应用于Serverless等场景 | |
| wasm3 | 高性能解释器 跨平台, iOS 等平台通用 轻量级引擎 | |
| WasmEdge | 在 Docker 中集成 使用 LLVM 编译后执行 社区提供了非常丰富的扩展能力 | |
| wasm-micro-runtime | 解释 & 编译两种运行模式 使用 LLVM 作为编译后端 运行速度最快的引擎 适用于 IoT 设备等资源受限的场景 | |
| V8 | 使用 TurboFan/LiftOff 后端编译 支持各种实验性的提案 适用于 Web/JavaScript 环境 |