OdinMonkey 的黄昏:告别 asm.js

Mozilla 已正式宣布,从 Firefox 148 开始,SpiderMonkey 引擎将停止对 asm.js 的优化。虽然 asm.js 代码将继续作为标准 JavaScript 运行,但曾经让其达到接近原生速度的专门优化将被默认禁用,并最终会被完全移除。

这一举动标志着从一种巧妙的“黑客手段”向正式 Web 标准的最终过渡。对于维护旧版网站的开发者而言,功能层面的过渡是无缝的,但性能优化的缺失使得重新编译为 WebAssembly (Wasm) 成为高性能 Web 应用的唯一可行路径。

asm.js 的遗产

asm.js 于 2013 年推出并在 Firefox 22 中发布,是 Mozilla 对在 Web 上运行原生速度代码这一挑战的战略性回应。当时,业界正在努力解决如何在不依赖专有插件或像 Google 的 Native Client (NaCl) 这样独立的沙箱的情况下实现高性能执行的问题。

asm.js 采取了一种高明的方法:它定义了 JavaScript 的一个严格、静态类型的子集。通过遵循这些规则,开发者可以编写代码,让 JavaScript 引擎能够即时识别并直接将其编译为原生机器码。这实现了几个里程碑式的成就:

  • 主流移植: 它实现了大规模 C/C++ 代码库(如 Unity 和 Unreal Engine)向浏览器的首次成功移植。
  • 快速原型设计: Epic Citadel 演示版仅用四天就成功移植到了 Web 端,证明了 Web 作为游戏平台的潜力。
  • Wasm 的基石: 最重要的是,asm.js 作为 WebAssembly 的概念验证。通过证明静态类型的二进制格式可以在浏览器中高效执行,它为正式的 Wasm 标准铺平了道路。

为什么现在进行转型

随着 WebAssembly 的广泛采用,为 asm.js 维护一条并行的优化路径已不再必要。Mozilla 提出了两个主要原因:

  1. 维护开销: 在 Wasm 旁边同时保留 asm.js 流水线需要巨大的工程投入。
  2. 安全性: 减少虚拟机 (VM) 中的代码量可以减少整体攻击面,从而增强浏览器的安全性。

Mozilla 的内部命名约定为这次转型增添了一抹诗意。asm.js 编译器,即 OdinMonkey,正在迎来它的“Ragnarök”(北欧神话中的诸神黄昏)。取而代之的是,BaldrMonkey(优化型 Wasm 编译器)和 RabaldrMonkey(基准 Wasm 编译器)将引领下一代 Web 性能。

社区观点与权衡

虽然官方公告被定性为一次成功,但开发者社区指出了 asm.js 与 WebAssembly 之间一些细微的权衡。

“隔离”问题

某些开发者认为,Wasm 与 JavaScript 环境的严格隔离是一把双刃剑。由于 Wasm 无法在没有垫片 (shims) 的情况下直接调用 Web API,且在 JS 与 Wasm 之间的零拷贝缓冲区 (zero-copy buffers) 处理上存在困难,一些人发现 asm.js 的方法更加灵活。

"I personally think this is a mistake... wasm is too isolated from javascript... You can't call most web apis from wasm."

性能边缘情况

虽然 Wasm 通常更快且生成的二进制文件更小,但一些开发者声称,对于特定的、高度优化的任务——例如 SHA256 哈希计算——asm.js 的实现仍然可以优于 Wasm 方案。

现实世界的影响:Figma 案例

行业案例说明了 asm.js 在专业 Web 工具演进过程中扮演的关键角色。例如,Figma 最初是一个 C++ 代码库。asm.js 是证明专业设计工具可以在浏览器中运行的关键技术。Figma 仅在建立起稳定的付费客户群后才转向 WebAssembly,由于 Wasm 避免了将 JavaScript 解析为抽象语法树 (AST) 的开销,其加载时间得到了显著提升。

结论

OdinMonkey 的落幕不仅仅是移除一段旧代码;它标志着 asm.js 实验的成功。通过证明 Web 可以处理原生速度的执行,asm.js 迫使了浏览器的演进,并扩展了“Web 应用”的定义。虽然有些人可能会怀念直接的 API 调用能力和子集-JS 方法的灵活性,但业界向标准化、二进制格式的迈进,确保了一个更安全、更高效、且更通用的 Web。

Sources