Why is NodeJS faster than Rust in computing the sum of the primes?
The answer can't be simple because V8 does a lot of transformations, but here's a major point:
Node's optimizing compiler dynamically adapts the types it uses (especially for array elements). It's able to use one word integers when they fit (and deoptimizes the function when it receives a non fitting value).
If I take your functions as they are, the Rust one takes 1.28ms to compute sum_prime(500)
when Node takes only 1.04ms (after some warming). If I change the u64
to u32
in the Rust code, then it only takes 608µs.
The JavaScript code I used:
function sum_primes(n) {
var primes = [];
var current = 2;
var sum = 0;
while (primes.length < n) {
if (primes.every(function (p) { return current % p != 0; })) {
sum += current;
primes.push(current);
}
++current;
}
return sum;
}
console.log(sum_primes(200));
// some warming
for (let i=0; i<100; i++) sum_primes(100);
console.time("primes");
console.log(sum_primes(500));
console.timeEnd("primes");
This JavaScript code is faster than your Rust code, but slower than this one:
use std::time::Instant;
fn sum_primes(n: usize) -> u32 {
let mut primes = Vec::new();
let mut current: u32 = 2;
let mut sum: u32 = 0;
while primes.len() < n {
if primes.iter().all(|p| current % p != 0) {
sum += current;
primes.push(current);
}
current += 1;
}
sum
}
fn main() {
println!("{}", sum_primes(200));
let s = Instant::now();
println!("{}", sum_primes(500));
println!("duration: {:?}", s.elapsed());
}