环境安装

如果你是 Windows,恭喜你,等待被环境折腾吧(当然如果你Visual Studio 安装得比较全:主要指 VC++ BuildTool,那环境问题就要好不少了)。Windows用户可以考虑搭配 Windows Subsystem for Linux(安装文档:https://docs.microsoft.com/zh-cn/windows/wsl/install-win10)。

首先必须是先安装好 Rust 环境,详见:《Hello,Rust》。

之后是安装 wasm-pack,详见:https://rustwasm.github.io/wasm-pack/installer/
安装指令为:

  1. curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

安装好后,会出现类似如下提示:
image.png

起步

先创建出项目

  1. cargo new rust-wasm

在项目中的 cargo.toml 中录入:

  1. [lib]
  2. crate-type = ["cdylib", "rlib"]
  3. [dependencies]
  4. wasm-bindgen = "0.2.63"
  5. wee_alloc = { version = "0.4.5", optional = true }
  6. [profile.release]
  7. # Tell `rustc` to optimize for small code size.
  8. opt-level = "s"

src/main.rs 修改为 src/lib.rs 并录入内容:

  1. use wasm_bindgen::prelude::*;
  2. // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
  3. // allocator.
  4. #[cfg(feature = "wee_alloc")]
  5. #[global_allocator]
  6. static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
  7. // 绑定 JS 方法
  8. #[wasm_bindgen]
  9. extern "C" {
  10. #[wasm_bindgen(js_namespace = console)]
  11. fn log(s: &str);
  12. fn alert(s: &str);
  13. }
  14. // 导出函数(可被 JS 调用)
  15. #[wasm_bindgen]
  16. pub fn print(s: &str) {
  17. log(s);
  18. }
  19. #[wasm_bindgen]
  20. pub fn wasm_alert(s: &str) {
  21. alert(s);
  22. }

接下来,执行 wasm-pack build 来构建 wasm 产物:
image.png
最后借助 webpack 编译 wasm 的能力实现互调用。

前端项目请参见:https://github.com/hstarorg/learning-rust/tree/master/rust-wasm/webroot,其中使用了 webpack5

性能差异

不涉及更细致的对比,仅仅通过计算“斐波拉切数列”(此处未作尾调用优化,优化后则不是耗时运算了)做了一个基本的测试,其结果如下:

数列 JavaScript Rust WebAssembly 性能比值 截图
1 ≈0.0042 ≈0.0073 ≈0.6 image.png
10 ≈0.0140 ≈0.0068 ≈2.1 image.png
35 ≈1676ms ≈40ms ≈41.9 image.png
40 ≈19068ms ≈412ms ≈46.3 image.png

结果也符合常规的预期,在非计算密集时,由于 WebAssembly 额外的成本是有一定的性能下降的。之后随着计算量的增大,WebAssembly 的性能对比 JavaScript 则有数据级的提升(10倍+)