Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link
Owner

djhworld commented Dec 30, 2018

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

This comment has been minimized.

Copy link
Owner

djhworld commented Dec 30, 2018

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