为什么 Node.js 在生成素数方面比 Rust 更快?

Sau*_*lik 4 node.js rust

这是分别在 Rust 和 Node.js 中生成素数的两个基本代码片段。我正在生成 100000 个素数。

use std::time::Instant;

fn main(){
    let start = Instant::now();
    generate_primes(100000);
    let elapsed = start.elapsed();
    // println!("{:?}", generate_primes(10));
    println!("Time taken: {}ms", elapsed.as_millis());
}

pub fn generate_primes(n: i32) -> Vec<i32> {
  let mut numbers:Vec<i32> = vec![0; 0];
  let mut iter:i32 = 2;
  let mut generated:i32 = 0;

  while generated < n {
    if is_prime(iter) {
      numbers.push(iter);
      generated += 1;
    }
    iter += 1;
  }

  numbers
}

fn is_prime(n: i32) -> bool {
    let limit = (n as f32).sqrt() as i32;

    for i in 2..=limit {
        if n % i == 0 {
            return false;
        }
    }

    true
}
Run Code Online (Sandbox Code Playgroud)

Rust 代码执行所需的时间:3274ms

编辑:运行后cargo run --release370ms

Node.js

const t0 = Date.now();
const primes = generatePrimes(100000);
const t1 = Date.now();
console.log(`Time taken: ${t1 - t0}ms`);

function generatePrimes(total) {
  let primes = [];
  let iter = 2;
  let generated = 0;

  while (generated < total) {
    if (isPrime(iter)) {
      primes.push(iter);
      generated++;
    }
    iter++;
  }
  return primes;
}

function isPrime(num) {
  for (let i = 2; i * i <= num; i++) {
    if (num % i === 0) {
      return false;
    }
  }
  return true;
}

Run Code Online (Sandbox Code Playgroud)

Javascript执行所花费的时间:333ms

我是 Rust(以及一般类型语言)的新手,所以肯定有一些我错过的优化。了解如何改进 Rust 的时间将会很有趣(即使使用cargo run --release,它也比 Node.js 慢)。

pro*_*-fh 9

在 JS 中,所有数字都是浮点数,因此除法/取模都是在浮点数上执行的。

然而,在当前的处理器中,整数除法/取模比浮点处理器慢得多(请参见此处)。

在 Rust 程序中,模数自然是根据整数计算的。当人为切换到浮点时,我得到了显着的改进(310ms --> 152ms)。

fn fmod(
    x: f64,
    y: f64,
) -> f64 {
    x - (x / y).floor() * y
}

fn is_prime(n: i32) -> bool {
    let limit = (n as f32).sqrt() as i32;
    for i in 2..=limit {
        if fmod(n as f64, i as f64) == 0.0 {
            return false;
        }
    }
    true
}
Run Code Online (Sandbox Code Playgroud)

更进一步,sqrt()如果我们比较平方,我们可以保存操作(顺便说一句,您在 JS 代码中执行了此操作)。(152 毫秒 --> 144 毫秒)

fn is_prime(n: i32) -> bool {
    for i in 2.. {
        if i * i > n {
            break;
        }
        if fmod(n as f64, i as f64) == 0.0 {
            return false;
        }
    }
    true
}
Run Code Online (Sandbox Code Playgroud)