WebAssembly是下一代Web客户端开发技术,目前已经是W3C的标准,94%的浏览器已经支持了WebAssembly标准。WebAssembly技术通过加载非Javascript语言(如C/C++、Rust、Go等)编写的源码经过交叉编译后生成的二进制文件,然后通过Javascript API调用相关函数完成计算,由于这些计算模块采用编译后的接近机器码的方式运行,因此WebAssembly技术可以让代码运行效率接近本机的运行效率,这大大提高了Web客户端程序的运行效率。当然,不建议使用WebAssembly操作浏览器DOM,否则运行效率可能会更低。
本文将使用一个Rust实现的计算指定位置的斐波那契数列值,对比Javascript实现和WebAssembly实现在运行效率上的差别。如果对Rust的安装及相关基本语法不了解,可参考本系列文档,可以从搭建开发环境开始学习。
斐波那契数列是这样一个数列:0、1、1、2、3、5、8、13、21、34、……。即:数列从0开始,然后第1、2项是1,然后从第 3 项开始,每一项都等于前两项之和。
1、安装wasm交叉编译器
在windows cmd或powershell窗口,执行以下命令安装交叉编译器:
rustup target add wasm32-unknown-unknown
2、创建Rust库项目
在windows cmd或powershell窗口,执行以下命令创建Rust库项目:
cargo new --lib hellowasm
修改Cargo.toml文件,将库类型修改为cdylib。在Cargo.toml文件的[dependencies]前添加以下内容:
[lib]
crate-type = ["cdylib"]
删除文件lib.rs原有内容,修改为以下内容:
#[no_mangle]
pub extern fn fbin(x: i32) -> i32 {
if x <= 1 {
return 1;
} else {
return fbin(x - 1) + fbin(x - 2);
}
}
no_mangle: 禁用对符号(symbol)名编码,表示在Javascript中依然采用fbin函数名调用本函数。extern关键字表示该函数可以在Javascript中调用。
3、编译为wasm文件
在hellowasm目录执行命令:
cargo build --release --target wasm32-unknown-unknown
编译成功后,会在hellowasm\target\wasm32-unknown-unknown\release目录中生成hellowasm.wasm文件。这个文件大小大概会超过1M,这是因为打包时cargo将所有依赖也添加到了.wasm文件中,否则可能该模块分发后不能正常运行。
将hellowasm.wasm文件copy到web服务器(如nginx、apache等,笔者采用的是npm的live-server)目录中即完成部署。
4、编写测试代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rust WebAssemblydemo</title>
</head>
<body>
<script>
//JS实现的斐波那契数列
function fnbin(x) {
if (x <= 1) {
return 1;
} else {
return fnbin(x - 1) + fnbin(x - 2);
}
}
// 加载wasm文件函数
function loadWebAssembly(fileName) {
return fetch(fileName)
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer)) // 编译
.then(module => { return WebAssembly.instantiate(module) }); //创建WebAssembly实例
};
//调用加载WebAssembly函数,注意wasm文件必须要本html文件在服务器同一目录,否则可能会出现404错误
loadWebAssembly('hellowasm.wasm').then(instance => {
console.time("WebAssembly")
console.log(instance.exports.fbin(45))
console.timeLog("WebAssembly");
console.time("Javascript");
console.log(fnbin(45))
console.timeLog("Javascript")
});
</script>
</body>
</html>
打开浏览器(Chrome、FireFox等现代浏览器,而不是IE这种老古董),访问服务器页面,点击F12打开浏览器开发者工具观察程序输出。下图是笔者环境的某次运行结果:可以看到,WebAssembly的效率比Javascript的效率要高。
上一篇:Rust语言基础语法
下一篇:Rust面向对象编程