4 ms·
There are two reasons: 1) The println! macro will lock and unlock the stdout every time it's called. 2) Rust's stdout is line-buffered by default. In my machin
by beltsazar 5y ago
There are two reasons: 1) The println! macro will lock and unlock the stdout every time it's called. 2) Rust's stdout is line-buffered by default.
In my machine the naive C implementation achieves 81.7 MiB/s, whereas a naive Rust implementation with println achieves 7.58 MiB/s.
When I acquired the stdout's lock once and use writeln!(&mut stdout, ...) instead of println, I got 8.15 MiB/s.
When I wrapped stdout with BufWriter, I got 299 MiB/s.
use std::io::{BufWriter, Write};
fn main() {
let stdout = std::io::stdout();
let stdout = stdout.lock();
let mut stdout = BufWriter::with_capacity(32 * 1024, stdout);
for i in 1..1_000_000_000 {
let _ = match (i % 3 == 0, i % 5 == 0) {
(true, true) => writeln!(&mut stdout, "FizzBuzz"),
(true, false) => writeln!(&mut stdout, "Fizz"),
(false, true) => writeln!(&mut stdout, "Buzz"),
(false, false) => writeln!(&mut stdout, "{}", i),
};
}
}
- yodelshady 5y agoWell TIL that printf won't lock stdout. Calling stdout.lock() by itself makes little difference for me. Using BufWriter as you have I get ~80 MiB/s (slightly ahead of PyPy). My implementation also has/had a String allocation in the loop, kicking that out got me to 120 MiB/s. I tend to write it as though the numbers/strings could be changed by a product manager at any time. Final edit/errata: I get up to 140 MiB/s by appending .to_string() in the integer case instead of format!(), which makes some sense. I didn't bother saving my original C implementation, but in retrospect I think I didn't use string concatenation, as I have with other languages. Redoing it with string-concatenation, C is slightly slower than Rust, 110 MiBs. Also makes sense as concatenation in C is slow.