I wrote a very rudimentary piece of code to calculate if a number is prime in Rust (compiled to WASM) and in JavaScript to benchmark the arithmetic performance.
I was fully expecting Rust/WASM to blow away JavaScript. In all other arithmetic benchmarks I've done Rust/WASM seems to have the edge over JavaScript or at least match it. However in this test, JavaScript seems to heavily outperform WASM and I don't really have an explanation to why that is.
Rust Code:
pub fn calculate_is_prime(number: u64) -> bool {
if number == 1 {
return false;
}
if number == 2 {
return true;
}
for i in 2..number {
if number % i == 0 {
return false;
}
}
return true;
}
#[wasm_bindgen]
pub fn bench_rs(max: u64) -> u64 {
(1..=max).map(|n| calculate_is_prime_rs(n) as u64).sum()
}
JavaScript code:
function calculateIsPrime(number) {
if (number === 1) {
return false;
}
if (number === 2) {
return true;
}
for (let i = 2; i < number; i++) {
if (number % i === 0) {
return false;
}
}
return true;
}
function bench_js(max) {
let tot = 0;
for (let n = 1; n <= max; n++) {
tot += calculateIsPrime(n);
}
return tot;
}
let max = 200000;
console.log(`Amount of primes under ${max} is ${bench_js(max)}`);
Basic sample project: https://github.com/Mcluky/Stack-Overflow-Rust-Wasm-Performance-Example
Things I've already checked/done:
- I made sure to always set the
--release
flag while building the rust code. - Ran the Rust code directly on my machine which is a lot faster than both JS and WASM so I suspect it has something to do with the WASM target.
- Replaced the integer type (u64) with a floating point (f64) in Rust since JavaScript is using floats but I got similar results.
- Tested over iterations to make sure it's consistent.
- Tried
while
instead offor-in
in the Rust version in case it wasn't as optimized as you'd think.