刚接触Rust wasm,请各看官高抬贵手。
根据网上资料,使用 wasm-pack
搭配wasm-bindgen
将Rust代码编译成 wasm。
搭好环境后,想对比一下rust-wasm与js的性能差距。
#[wasm_bindgen]
pub fn cpu_calc(count: i32) {
let mut result = 1;
// 计算多少数字下
for i in 2..count {
let num: f64 = i as f64;
let after_sqrt = num.sqrt() as i32 + 1;
let mut flag = true;
for j in 2..after_sqrt {
let dividing = i % j;
if dividing == 0 {
flag = false;
break;
}
}
if flag {
result = i;
}
}
// 调用浏览器控制台打印
console_log(&format!("rust 素数:{}", result));
}
function cpuCalc(num) {
let result = 0;
for (let i = 2; i < num; i++) {
let flag = true;
for (let j = 2; j < Math.sqrt(i); j++) {
if (i % j === 0) {
flag = false;
break;
}
}
if (flag) {
result = i;
}
}
console.log('js素数:', result);
}
之后通过js分别调用这两个方法,进行1,000,0000 (100w) 以内的质数计算。并打印最大的质数。
多刷新页面几次,等耗时看起来基本稳定。
计算性能和js基本差不多。
而调用wasm 的时候也是同步的代码。
看来js对于处理的cpu计算任务性能还是可以的。
但是总觉得应该wasm更快一点的。
那wasm在什么场景下比js具有优势呢,这个还需要继续深入。
计算斐波那契数列可使用递归的方式或while循环的方式。循环40次。
下面对两种情况做讨论
fn fib_rec(num: i16) -> i64 {
if num < 2 {
return 1; // rust 中值要return
}
fib_rec(num - 1) + fib_rec(num - 2)
}
#[wasm_bindgen]
pub fn fib_recursion(time: i16) -> i64 {
let mut result = 0;
let mut i = 1;
while i < time {
result = fib_rec(i);
i += 1;
}
result
}
function fibRec(num) {
if (num < 2) return 1;
return fibRec(num - 1) + fibRec(num - 2);
}
function fibRecursion(time) {
let i = 1;
let result = 0;
while (i < time) {
result = fibRec(i++);
}
return result;
}
wasm代码2s左右,js3s左右,数据量多的情况下。
#[wasm_bindgen]
pub fn fib(num: i32) -> i64 {
let mut result = 0;
for i in 1..num {
let mut num1 = 1;
let mut num2 = 1;
let mut j = 1;
while j < i {
j += 1;
let temp = num2;
num2 = num2 + num1;
num1 = temp;
result = num2;
}
}
result
}
function fib(num) {
let result = 0;
for (let i = 1; i < num; i++) {
let num1 = 1;
let num2 = 1;
let j = 1;
while (j < i) {
j += 1;
let temp = num2;
num2 = num1 + num2;
num1 = temp;
result = num2;
}
}
return result;
}
可见直接使用while循环比递归方式速度快不少。
运行速度上rust-wasm 更胜一筹
rust-wasm 速度更快。
let num = 0;
for(let i = 0;i<10_000_000;i++){
num += i;
}
console.log('js add', num);
#[wasm_bindgen]
pub fn add_range(a:i32,b:i32) -> i64 {
let mut sum =0;
for i in a..b {
sum += i as i64;
}
sum
}
console.log('rust add',add_range(0,10_000_000));
数据越大差距越明显。神奇的是wasm性能始终在0.几毫秒。
怕是被rust优化成等差求和了?
计算素数时,性能相近。
计算斐波那契数列时,Rust 性能更好。
为什么计算素数性能相近,而计算斐波那契数列rust较快。值得研究。