You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Arc<Mutex<anyhow::Result<()>>>时Rust Rayon为何耗时更长?

为什么加锁后程序耗时暴增?

你的核心问题是Mutex的竞争直接让并行效率完全丧失:

  • 你用Arc<Mutex<Vec<_>>>让每个线程处理完文件后都去抢锁,再往Vec里push结果。但push本身是极快的操作,可抢锁的过程是串行的——每个线程都得等前一个线程释放锁才能执行,相当于把原本的并行任务硬生生拖成了串行执行,大部分时间都花在等待锁释放上,而非真正处理文件。
  • 无锁版本(推测你是去掉了结果收集逻辑)没有锁的竞争,线程能真正并行处理任务,所以耗时极低。
正确的做法:用Rayon自带的结果收集机制

Rayon已经内置了高效的并行结果收集能力,完全不需要手动加Mutex。把for_each换成map,再用collect直接得到结果Vec,全程无锁,性能和无锁版本一致:

fn main() -> anyhow::Result<()> {
    let (files, _) = utils::get_files_from_folder(input_folder)?;

    // Rayon自动处理并行结果的收集,无需手动加锁
    let results: Vec<anyhow::Result<()>> = files.par_iter().map(|path| {
        if let Some(extension) = path.extension() {
            if extension == "txt" {
                redact::redact_txt_and_write_json(path, &regex_vec, &output_folder)
            } else {
                eprintln!(
                    "{}INVALID EXTENSION: {} - Not yet implemented",
                    *RED_ERROR_STRING,
                    extension.to_string_lossy(),
                );
                // 并行任务里别直接exit,返回错误更合理
                Err(anyhow::anyhow!("invalid extension: {}", extension.to_string_lossy()))
            }
        } else {
            eprintln!("{}EXTENSION not found", *RED_ERROR_STRING);
            Err(anyhow::anyhow!("extension not found for path: {}", path.display()))
        }
    }).collect();

    println!("{:?}", results);
    Ok(())
}
额外优化点
  • 别在并行任务里直接std::process::exit(1):多线程运行时,任意线程调用exit会直接终止整个程序,可能导致其他线程的任务半途而废,换成返回错误统一处理更稳妥。
  • 把par_iter_mut改成par_iter:你的代码里并没有修改path,用不可变迭代器更安全,也能避免不必要的可变借用开销。

内容的提问来源于stack exchange,提问作者Jim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 13:20:30