Skip to content

Instantly share code, notes, and snippets.

@djhworld
Created December 30, 2018 10:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save djhworld/ced7eabca8e0c06d5b65917e87fb8745 to your computer and use it in GitHub Desktop.
Save djhworld/ced7eabca8e0c06d5b65917e87fb8745 to your computer and use it in GitHub Desktop.
improved version
use std::collections::HashMap;
use std::io;
use std::io::BufRead;
struct Counter {
items: HashMap<String, usize>,
}
impl Counter {
fn new() -> Counter {
return Counter {
items: HashMap::new(),
};
}
fn add(&mut self, st: &str) {
match self.items.get_mut(st) {
Some(x) => {
*x += 1;
}
None => {
self.items.insert(st.to_owned(), 1);
}
}
}
fn render(&self) {
for (key, val) in &self.items {
println!("{}\t{}", val, key);
}
}
}
fn using_read_line_with_reuse(c: &mut Counter) {
let st = io::stdin();
let mut stdin = st.lock();
let mut line = String::new();
loop {
line.clear();
let r = stdin.read_line(&mut line);
match r {
Ok(0) => break,
Ok(_) => {
c.add(line.trim_end());
}
Err(err) => {
println!("{}", err);
break;
}
};
}
}
fn using_read_line(c: &mut Counter) {
let st = io::stdin();
let mut stdin = st.lock();
loop {
let mut line = String::new();
let r = stdin.read_line(&mut line);
match r {
Ok(0) => break,
Ok(_) => {
c.add(line.trim_end());
}
Err(err) => {
println!("{}", err);
break;
}
};
}
}
// uses lines() iterator
fn using_bufread_lines(c: &mut Counter) {
for r in io::stdin().lock().lines().filter_map(Result::ok) {
c.add(r.as_str());
}
}
fn main() {
let mut c = Counter::new();
// using_bufread_lines(&mut c);
//using_read_line(&mut c);
using_read_line_with_reuse(&mut c);
c.render();
}
@djhworld
Copy link
Author

This is a follow on gist from https://gist.github.com/djhworld/d49f9acae96e32465e05f9d16930448c and includes some changes suggested and discussed in reddit thread https://www.reddit.com/r/rust/comments/aaood3/go_version_of_program_is_40_quicker_than_rust/

Suggested implementations were

  • using bufread.lines() iterator instead
  • locking stdin
  • locking stdin AND reusing the String on each iteration of the loop

I've tested all 3 implementations using my crude benchmark script (see previous gist) and strategy #3 comes out on top as the best performer, while the other 2 implementations are still slightly slower than the Go version.

screenshot 2018-12-30 at 10 54 11

@djhworld
Copy link
Author

Another suggestion was to use the change the hashmap implementation to the crate hashbrown, here are the results

screenshot 2018-12-30 at 11 20 16

The buf.lines() implementation is now almost the same as the go version, and the other 2 rust implementations are faster

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment