Skip to main content

WebAssembly (Wasm)

WebAssembly 是一种运行在现代网络浏览器中的新型代码,并且提供新的性能特性和效果。它并不是用来取代 JavaScript 的,而是与之互补。它允许 C/C++、Rust 等语言编译到 Web 上运行,主要用于解决 JS 在 CPU 密集型计算(如音视频处理、3D 渲染)上的性能瓶颈

为什么 WebAssembly 比 JavaScript 快?

面试官经常会问:“JS 经过 V8 的 JIT 优化已经很快了,为什么还要搞 Wasm?”

  • 体积更小,加载更快:Wasm 是二进制格式,比起文本格式的 JS,下载速度更快,且浏览器不需要进行词法分析和语法分析(Parse)。
  • 跳过编译阶段:JS 需要经过 JIT(即时编译)将热点代码转化为机器码,而且如果类型改变还会发生“去优化(Deoptimization)”被打回原形。Wasm 本身就是静态类型的汇编级代码,浏览器拿到后直接就能翻译成底层机器码执行,性能极其稳定,不存在去优化。
  • 内存管理更高效:JS 依赖引擎的垃圾回收(GC),GC 运行时会导致主线程短暂卡顿(Stop-the-world)。Wasm 通常使用手动内存管理(如 Rust/C++ 编译过来的代码),没有 GC 的运行时开销。

WebAssembly 不是什么?

  • 不是汇编语言:它是一种底层的“虚拟指令集架构”,并不依赖于特定的物理硬件(所以能在各种浏览器里跨平台跑)。
  • 不能直接操作 DOM:这是很多人的误区。目前 Wasm 没有直接访问 DOM 的能力,它必须通过 JS 的胶水代码来间接修改 DOM。因此,用 Wasm 写普通的 UI 页面毫无意义,甚至会因为与 JS 频繁通信的开销而变得更慢。
  • 不是 JS 的替代品:Wasm 的定位是辅助引擎,专门干 JS 不擅长的脏活累活。

典型应用场景

  1. 音视频解码/编辑:B 站的 Web 端视频播放器,利用 Wasm 移植了底层的 C++ 解码库(如 FFmpeg),实现了在浏览器端直接硬解 HEVC/H.265 格式的视频。
  2. 大型桌面软件 Web 化
    • Figma:网页版的设计工具,底层图形渲染引擎由 C++ 编译为 Wasm。
    • AutoCAD / Photoshop:这两家都通过 Wasm 将他们庞大的 C++ 桌面端代码库原封不动地搬到了浏览器里。
  3. 图像处理与游戏引擎:在浏览器中运行 Unity、Unreal 引擎导出的 3D 游戏,或者进行复杂滤镜的实时计算。
  4. 3D 模型压缩与极速解析 (Draco):Google 开源的 Draco 3D 数据压缩算法。在 Three.js 等 WebGL/WebGPU 项目中,通过加载体积极小的 Draco 压缩模型,利用由 C++ 编译而来的 Wasm 版解码器,在浏览器端进行极其吃 CPU 算力的位运算与几何解码。解压后的顶点数据直接通过 ArrayBuffer 零拷贝共享给 JS 并推入 GPU,极大缩短了 3D 场景的首屏加载时间。

Wasm 与 JS 是如何通信的?

  • WebAssembly 模块导出了一个实例,JS 可以直接像调用普通 JS 函数一样调用 Wasm 里的函数(比如 wasmInstance.exports.fibonacci(10))。
  • 内存共享:它们之间传递复杂数据(如大数组、图像数据)不能靠传参(因为会有拷贝开销),而是通过一块 共享的线性内存 (WebAssembly.Memory)。JS 将数据写入这块 ArrayBuffer 内存,Wasm 直接从内存同一位置读取处理,处理完 JS 再去读,实现“零拷贝”极速通信。