Rust WASM 与 JS 计算性能对比

2023-05-16

前言

刚接触Rust wasm,请各看官高抬贵手。

简介

根据网上资料,使用 wasm-pack 搭配wasm-bindgen将Rust代码编译成 wasm。
搭好环境后,想对比一下rust-wasm与js的性能差距。

  • 环境
    • OS: Deepin 20.7.1 apricot
    • Kernel: Linux 5.15.34
    • CPU: Intel Core m3-7Y30 @ 4x 2.6GHz
    • RAM: 4GB
    • 浏览器: Microsoft Edge 版本 107.0.1418.35 (正式版本) (64 位)
  • Rust 依赖
    • rustc 1.60.0
    • wasm-bindgen: 0.2

方案:计算素数

Rust 函数

#[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));
}

JS 函数

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) 以内的质数计算。并打印最大的质数。

结果

多刷新页面几次,等耗时看起来基本稳定。

先运行wasm方法,再执行js方法。

在这里插入图片描述

先执行js方法,再执行wasm方法。

在这里插入图片描述

计算素数小结

计算性能和js基本差不多。
而调用wasm 的时候也是同步的代码。
看来js对于处理的cpu计算任务性能还是可以的。
但是总觉得应该wasm更快一点的。

那wasm在什么场景下比js具有优势呢,这个还需要继续深入。

方案2:计算斐波那契数列

计算斐波那契数列可使用递归的方式或while循环的方式。循环40次。
下面对两种情况做讨论

递归实现

Rust 函数

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
}

JS函数

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左右,数据量多的情况下。

while循环实现

Rust函数

#[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
}

JS函数

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 速度更快。

普通加法计算

JS

let num = 0;
for(let i = 0;i<10_000_000;i++){
    num += i;
}
console.log('js add', num);

Rust

#[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
}

JS调用wasm

console.log('rust add',add_range(0,10_000_000));

结果

0 - 10,000

在这里插入图片描述

0 - 1千万

在这里插入图片描述

0 - 10亿

在这里插入图片描述

数据越大差距越明显。神奇的是wasm性能始终在0.几毫秒。
怕是被rust优化成等差求和了?

小结

计算素数时,性能相近。
计算斐波那契数列时,Rust 性能更好。
为什么计算素数性能相近,而计算斐波那契数列rust较快。值得研究。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rust WASM 与 JS 计算性能对比 的相关文章

随机推荐