为什么这个hashmap搜索比预期慢?

时间:2015-08-18 11:40:11

标签: rust

检查密钥的哈希映射的最佳方法是什么? 目前我正在使用这个:

let hashmap = HashMap::<&str, &str>::new();  // Empty hashmap

let name = "random";

for i in 0..5000000 {
    if !hashmap.contains_key(&name) { 
        // Do nothing
        }
}

在大多数情况下这似乎很快,并且如图所示运行时需要0.06秒,但是当我在下面的循环中使用它时,它变得非常慢并且在我的机器上花费将近1分钟。 (这是用cargo run --release编译的)。 该代码旨在打开一个外部程序,并循环该程序的输出。

let a = vec!["view", "-h"]; // Arguments to open process with
let mut child = Command::new("samtools").args(&a)
                                        .stdout(Stdio::piped())
                                        .spawn()
                                        .unwrap();

let collect_pairs = HashMap::<&str, &str>::new();

if let Some(ref mut stdout) = child.stdout {
    for line in BufReader::new(stdout).lines() {
        // Do stuff here          
        let name = "random";
        if !collect_pairs.contains_key(&name) {
            // Do nothing
        }
    }
}

由于某些原因,添加if !collect_pairs.contains_key(行会使运行时间增加近一分钟。孩子的输出约为500万行。所有这些代码都存在于fn main()

修改

这似乎解决了问题,导致运行时间很短,但我不知道为什么!hashmap.contains_key在这里效果不好:

let n: Option<&&str> = collect_pairs.get(name);
if match n {Some(v) => 1, None => 0} == 1 {
  // Do something
}

2 个答案:

答案 0 :(得分:3)

要考虑的一件事是HashMap<K, V>默认使用加密安全散列算法,因此它本质上总是有点慢。

get()归结为

self.search(k).map(|bucket| bucket.into_refs().1)

contains_key

self.search(k).is_some()

因此,get()对你来说更快,对我来说似乎很陌生,它做得更多!

此外,

if match n {Some(v) => 1, None => 0} == 1 {

这可以更加惯用地编写为

if let Some(v) = n {

答案 1 :(得分:0)

我发现了我的问题,对不起我直到现在还没有找到。我没有正确检查if !collect_pairs.contains_key(&name)的返回。由于某种原因,它返回true,导致if块的其余部分被运行。我以为它正在评估false。谢谢你的帮助