Rust (🦀) vs Mojo (🔥): So which one is actually faster?
Hello, dear reader,
Mojo programming language has been gaining traction and you might find articles where it is faster than Rust like Mojo vs. Rust: is Mojo 🔥 faster than Rust 🦀 ?. I'm always skeptical of benchmarks, tell me who must win and I'll come up with benchmark. That blog post was discussed in multiple places, a good reading can be Mojo vs. Rust: is Mojo faster than Rust? that points to multiple issues with Rust code.
Here I want to take Rust code from Tail Call Optimization (TCO) part of Mojo vs. Rust: is Mojo 🔥 faster than Rust 🦀 ? and slightly modify it to make more Rusty. Original code was
fn recursive(x: usize){
if x == 0 {
return;
}
let mut stuff = Vec::with_capacity(x);
for i in 0..x {
stuff.push(i);
}
recursive(x - 1)
}
fn main() {
recursive(50_000);
}
I'm going to do three things:
Actually use
stuff
vector inside recursion. Will calculate the sum of all the elements inside the vector;Use scope to make sure
stuff
is dropped. Rust compiler heavily relies on scopes!Add another parameter to
recursive
to make sure compiler won't get rid of computed sum from previous step.
Modified version is
fn recursive(x: usize, sum: usize) -> usize {
if x == 0 {
return sum;
}
let current_sum = {
// Create vector and populate it
let mut stuff = Vec::with_capacity(x);
for i in 0..x {
stuff.push(i);
}
// Calculate the sum using good old for loop
let mut s: usize = 0;
for v in stuff {
s += v;
}
s
};
let updated_sum = current_sum + sum;
recursive(x - 1, updated_sum)
}
fn main() {
let n: usize = 50000;
let r = recursive(n, 0);
}
Let's adjust Mojo code to look similar to Rust, here is what we get
fn recursive(x: Int, sum: Int) -> Int:
if x == 0:
return sum
# Create list and populate it
var stuff = List[Int](x)
for i in range(x):
stuff.append(i)
# Calculate the sum using good old for loop
var curr_sum: Int = 0
for v in stuff:
curr_sum = curr_sum + v[]
var updated_sum = sum + curr_sum
return recursive(x - 1, updated_sum)
fn main():
var r = recursive(50_000, 0)
Let's compile them and benchmark using hyperfine
Results:
Mojo runs 4101.0 ms ± 87.8 ms (mean ± standard deviation) with maximum resident set size 12048 KBytes
Rust runs 655.4 ms ± 3.8 ms (mean ± standard deviation) with maximum resident set size 2464 KBytes
We can conclude that Mojo is 6.25 slower than Rust and requires 4.88 times more memory!
My environment:
Host OS: Microsoft Windows 10 Pro N x64 [Version 22H2, OS build 19045.4355]
WSL2 as VM with Ubuntu 24.04 LTS
CPU: AMD Ryzen 9 3950X 16-Core Processor 3.5 GHz
Memory: DDR4-2933 GHz 32 GB
Rust compiler: rustc 1.78.0 (9b00956e5 2024-04-29), host: x86_64-unknown-linux-gnu, LLVM version: 18.1.2
Mojo compiler: mojo 24.3.0 (9882e19d)
PS: Please, do not take this article too seriously ☺
Comments and suggestions are welcome! Thank you for your time.