微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Rust中的人造丝和Indicatif导致内存泄漏

如何解决Rust中的人造丝和Indicatif导致内存泄漏

因此,我正在尝试对哈希进行详尽的搜索。哈希本身在这里并不重要。因为我想使用cpu的所有处理能力,所以我在使用Rayon获取线程池和许多任务。搜索算法如下:

let (tx,rx) = mpsc::channel();

let original_hash = String::from(original_hash);

rayon::spawn(move || {
    let mut i = 0;
    let mut iter = SenhaIterator::from(initial_pwd);
    while i < max_iteracoes {
        let pwd = iter.next().unwrap();

        let clone_tx = tx.clone();
        rayon::spawn(move || {
            let hash = calcula_hash(&pwd);
            clone_tx.send((pwd,hash)).unwrap();
        });

        i += 1;
    }
});

let mut last_pwd = None;
let bar = ProgressBar::new(max_iteracoes as u64);

while let Ok((pwd,hash)) = rx.recv() {
    last_pwd = Some(pwd);
    if hash == original_hash {
        bar.finish();
        return last_pwd.map_or(ResultadoSenha::SenhaNaoEnconTrada(None),|s| {
            ResultadoSenha::SenhaEnconTrada(s)
        });
    }
    bar.inc(1);
}
bar.finish();
ResultadoSenha::SenhaNaoEnconTrada(last_pwd)

只是一个高层次的解释:随着任务完成工作,它们向主线程发送一对(密码,哈希),该哈希将哈希与原始哈希(我正在尝试查找的哈希)进行比较的密码)。如果它们匹配,那就太好了,我将使用一个表示成功的枚举值生成原始哈希值的密码返回main。在所有迭代结束之后,我将使用一个enum值返回main,该值指示未找到哈希,但是使用最后一个密码,因此我可以在以后的运行中从这一点重试。

我正尝试使用Indicatif显示进度条,这样我就可以了解进度。

但是我的问题是该程序正在增加其内存使用量,而没有明确的原因。如果我让它运行10亿次迭代,它会慢慢增加内存,直到填满所有可用的系统内存。

但是当我注释bar.inc(1);行时,该程序的行为与预期的一样,并且使用了正常的内存。

我已经使用Rayon和Indicatif创建了一个测试程序,但是没有进行哈希计算,并且可以正常工作,没有内存异常。

这使我认为我的代码中的内存管理有问题,但是看不到明显的东西。

解决方法

我找到了解决方案,但是我仍然不确定为什么它可以解决原始问题。

我要解决的问题是将进度代码传输到第一个生成的闭包中。请看下面的第6和19行:

let (tx,rx) = mpsc::channel();

let original_hash = String::from(original_hash);

rayon::spawn(move || {
    let mut bar = ProgressBar::new(max_iteracoes as u64);
    let mut i = 0;
    let mut iter = SenhaIterator::from(initial_pwd);
    while i < max_iteracoes {
        let pwd = iter.next().unwrap();

        let clone_tx = tx.clone();
        rayon::spawn(move || {
            let hash = calcula_hash(&pwd);
            clone_tx.send((pwd,hash)).unwrap();
        });

        i += 1;
        bar.inc();
    }
    bar.finish();
});

let mut latest_pwd = None;

while let Ok((pwd,hash)) = rx.recv() {
    latest_pwd = Some(pwd);
    if hash == original_hash {
        return latest_pwd.map_or(PasswordOutcome::PasswordNotFound(None),|s| {
            PasswordOutcome::PasswordFound(s)
        })
    }
}
PasswordOutcome::PasswordNotFound(latest_pwd)

第一个生成器关闭的作用是获取下一个密码,以尝试将其传递给工作程序任务,该工作程序计算相应的哈希并将该对(密码,哈希)发送到主线程。主线程将等待来自rx通道的对,并与预期的哈希进行比较。

我仍然缺少的是为什么跟踪外线程的进度会泄漏内存。我无法确定真正泄漏的是什么。但是它现在正在工作,我对结果感到满意。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。