How do I go about finding out what's keeping the Rust version from being faster?
In the general case you would use a profiler like Linux's perf
tool to give you a rundown of which functions are eating up all your time. But perf
is broken on my computer at the moment and I don't feel like fixing it, so let's try some more Rust-specific advice. :)
The first thing to do is note that print!
is a macro (note the exclamation point!), which means that it's expanding at compile-time to do... something. We can figure out what that something is by passing --pretty expanded
to the compiler, yielding this:
#![feature(phase)]
#![no_std]
#![feature(globs)]
#[phase(plugin, link)]
extern crate "std" as std;
#[prelude_import]
use std::prelude::*;
fn main() {
let mut reader = io::stdin();
for line in reader.lock().lines() {
match line {
Ok(l) =>
match (&l,) {
(__arg0,) => {
#[inline]
#[allow(dead_code)]
static __STATIC_FMTSTR: &'static [&'static str] = &[""];
::std::io::stdio::print_args(&::std::fmt::Arguments::new(__STATIC_FMTSTR,
&[::std::fmt::argument(::std::fmt::Show::fmt,
__arg0)]))
}
},
Err(_) => continue ,
}
}
}
Yikes... that's a whole lot of stuff just for printing a line via a type-safe format string. In truth we really don't care about type-safe format strings in this application, given that we want an apples-to-apples comparison to C, so we can get rid of the macro entirely... but what to replace it with? I could give you the step-by-step, but instead I'll point you to the stdio docs and let you poke around at your leisure: http://doc.rust-lang.org/std/io/stdio/
Here's the result of me perusing the docs there:
use std::io;
fn main() {
let mut reader = io::stdin();
let mut writer = io::stdout();
while let Ok(c) = reader.read_u8() {
writer.write_u8(c);
}
}
This looks much more directly comparable to your C program.
(If you're wondering what while let foo
does, it is simply treated as an infinite loop that breaks whenever you get an enum that isn't foo
. In this case, reader.read_u8()
returns an IoResult
, and will give you the Ok
variant when it gets a char or the Err
variant when it hits EOF. See read_u8
's documentation here: http://doc.rust-lang.org/std/io/trait.Reader.html#method.read_u8)
I'm sure this program could be optimized further, perhaps by investigating the stdin_raw()
and stdout_raw()
functions mentioned in the stdio docs. But this should give you a good starting point, and give you the tools to dig deeper yourself.
EDIT: Changed read_char
to read_u8
for better analogy with C.
cargo build --release
orrustc -O file.rs
Additionally, if you want to find more information about the assembly produced, you can pass--emit asm
to rustc \$\endgroup\$