Performance — Haskell vs Rust Link to heading
In the previous article, we wrote a simple Haskell program that reverses characters within each word. We also wrote the same program in Rust for comparison. In terms of readability and conciseness, Haskell was the clear winner, but what about the performance? In this article, we want to have a look at how the performance compares between the two.
Haskell Implementation Link to heading
As a recap, below is the Haskell implementation of the program that reads in text, reverses characters in each word, and prints out.
-- reverse.hs
main = do
line <- getLine
if null line
then return ()
else do
putStrLn (reverseWords line)
main
reverseWords :: String -> String
reverseWords = unwords . map reverse . words
Let’s compile with optimization and run on ~6MB text file.
$ ghc -O2 reverse
$ time ./reverse < input.txt > output1.txt
real 0m0.265s
user 0m0.236s
sys 0m0.027s
Rust Implementation Link to heading
Now, let’s do the same thing in Rust.
// reverse.rs
use std::io::{stdin, Result};
fn main() -> Result<()> {
let input = stdin();
let iter = input.lines().map(|line| line.map(reverse_words));
for line in iter {
println!("{}", line?);
}
Ok(())
}
fn reverse_words(line: String) -> String {
line.split_whitespace()
.map(|word| word.chars().rev().collect::<String>())
.collect::<Vec<_>>()
.join(" ")
}
Let’s compile with optimization and run
$ rustc -C opt-level=3 -o reverse_rs reverse.rs
$ time ./reverse_rs < input.txt > output
real 0m0.327s
user 0m0.108s
sys 0m0.219s
Hmm, somehow, Rust version runs much slower than Haskell. But wait, there is something peculiar with this. The system time is much faster with Haskell while user time much faster with Rust. Typically, user time is what measure the actual time spent within the user-written program, while system time typically is IO operations.
It turns out that writing each line directly to stdout() in Rust is very slow, taking up a lot of system time. One solution is to use BufWriter instead.
--- before
+++ after
@@ -1,10 +1,11 @@
-use std::io::{stdin, Result};
+use std::io::{stdin, stdout, BufWriter, Result, Write};
fn main() -> Result<()> {
let input = stdin();
let iter = input.lines().map(|line| line.map(reverse_words));
+ let mut output = BufWriter::new(stdout());
for line in iter {
- println!("{}", line?);
+ writeln!(output, "{}", line?)?;
}
Ok(())
}
With the change, let’s re-compile and re-run the program
$ rustc -C opt-level=3 -o reverse_rs reverse.rs
$ time ./reverse_rs < input.txt > output
real 0m0.093s
user 0m0.071s
sys 0m0.021s
Below chart summarizes our finding. The same program written in Rust runs ~2.5x faster than the same program written in Haskell.

Conclusion Link to heading
Obviously, this is just a single data point, and we shouldn’t conclude all programs written in Rust are always faster than Haskell. However, this result is in ballpark with other benchmark results, such as Benchmarks Game.

My conclusion is that though Haskell may not replace C/C++/Rust in high-performance applications, it still can be a good alternative in place of other slower but garbage-collected languages, such as C#, Java, or Go.