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());
}