在公司项目里的一个小角落,尝试使用 Rust + WebAssembly 加速应用里部分计算
选择
首先要分清项目里 WebAssembly 的定位
- 应用主体:完成绝大多数逻辑,JS 只作为加载入口和少部分事件绑定桥梁
- 工具库:分担一些复杂和耗时的计算,由 JS 决定什么时候调用 wasm 模块函数,通常情况下,由 JS 管理 wasm 的线性内存
此次小 Demo 属于第 2 种情况
选择 Rust Target
rust 支持 wasm32-unknown-unknown
和 wasm32-unknown-emscripten
两种编译目标,后者除了wasm 外,还生成了 emscripten 风格的 JS 作为入口,与 asm.js 的调用风格统一。不过会添加好些运行时代码,与 wasm 之间也隔着一层封装。基于上一项的选择,我们选择前者
|
WebAssembly 考量
数据类型问题
WebAssembly 当前只支持几种有限的数字类型,i32/i64/f32/f64,JS 与之交互时,除了 number 以外的值都要有序列化/反序列化处理。
字符串
可使用 TextEncoder/TextDecoder 将 JS 字符串序列化为 utf-8 字节流,在 Rust 端先将字节流解析为字符串,再使用。
数组
JS 直接操作 wasm 示例的内存,将数组数据写入,调用 wasm 方法时,将数组起始的指针以及数组长度作为参数。
|
|
JS 端
|
demo.ts
|
编译 WASM
|
WASM 瘦身
参见此文
Cargo.toml 中一些设定
|
例子
- Hello Rust
- https://arkada38.github.io/2017/12/04/rust-wasm-string-to-uppercase/
- https://stackoverflow.com/questions/49014610/passing-a-javascript-string-to-a-rust-function-compiled-to-webassembly
- Small WebAssembly Binaries with Rust + Emscripten