浏览器C++和WebAssembly加速
使用WebAssembly在浏览器中运行C++和Rust
JavaScript在很多方面都很出色,但它并非为重型计算而设计。如果你想运行物理引擎、实时处理视频或在浏览器中编译代码,JavaScript可能太慢了。WebAssembly(简称Wasm)通过让你直接在浏览器中运行用C++、Rust或Go等语言编写的代码,以接近原生速度来解决这个问题。
WebAssembly的工作原理
你用C++或Rust等语言编写代码,将其编译成.wasm二进制文件,然后与JavaScript一起加载到浏览器中。浏览器将这个二进制文件编译成机器码,就像原生应用程序一样。结果是计算密集型任务的运行速度比等效的JavaScript快得多。
.wasm文件在沙盒环境中运行——它不能直接访问DOM或文件系统。相反,它通过一个定义良好的接口与JavaScript通信。JavaScript调用WebAssembly模块导出的函数,WebAssembly模块可以调用从JavaScript导入的函数。数据通过共享内存缓冲区共享。
不同语言的工具链
最简单的入门方式取决于你的语言。对于C和C++,Emscripten是最成熟的工具链。它将你的代码编译成WebAssembly,并提供处理加载和内存管理的JavaScript胶水代码。它还支持用于图形的SDL、POSIX线程和SIMD指令。
对于Rust,wasm-pack是标准工具。它与Cargo(Rust的包管理器)集成,并自动生成TypeScript绑定。对于Go,TinyGo生成小的WebAssembly二进制文件。而AssemblyScript让你使用类似TypeScript的语法编写WebAssembly。
性能特点
WebAssembly在CPU密集型任务(如数学、密码学、压缩、物理和机器学习推理)上以接近原生速度运行。启动时间比JavaScript快,因为二进制格式可以更高效地编译。流式编译让浏览器在下载WebAssembly的同时进行编译,进一步缩短了启动时间。
为了获得最大性能,请启用SIMD指令进行并行操作,使用Web Workers在主线程之外运行WebAssembly,并尽量减少JavaScript和WebAssembly之间的调用次数——每次跨越都有开销。
实际应用
许多以前在浏览器中不可能或不切实际的事情现在变得可行。图像和视频处理可以实时进行——FFmpeg.wasm在浏览器中运行完整的FFmpeg库。密码学库可以以原生速度工作。像Box2D和Rapier这样的3D物理引擎为游戏和模拟提供动力。
也许最令人印象深刻的用例是在浏览器中运行整个应用程序。Unity和Unreal Engine都可以将游戏导出到WebAssembly,将主机质量的游戏带到浏览器中。AutoCAD通过WebAssembly在浏览器中运行。而像SQLite、Figma和Google Earth等工具都拥有重要的WebAssembly组件。
未来
WebAssembly不再仅仅用于浏览器。WASI(WebAssembly系统接口)正在标准化文件、网络和时钟的系统调用,使WebAssembly能够在服务器、边缘设备上运行,甚至作为通用插件格式。组件模型将允许用不同语言编写的WebAssembly模块无缝互操作。WebAssembly正在成为代码的通用运行时,无论它在何处运行。
