为何Rust线程将闭包内逻辑提取为函数后性能大幅提升?
Rust多线程文件压缩工具的性能优化疑问
我正在学习Rust,基于书中概念实现了一个文件压缩工具。尝试用标准库的mpsc实现多线程压缩流程时,初代多线程方案居然比单线程还慢。
把线程闭包里的大部分逻辑提取到独立的encode_segment函数后,性能暴涨:压缩70MB文件时,单线程平均耗时约1700ms,初代多线程约2000ms,改进后仅约600ms(均为50次运行的平均值)。
性能差异相关代码片段
提取后的独立编码函数
// 原线程闭包内的逻辑现已提取至此函数: fn encode_segment<T>( t: &mut T, offset_from_start: usize, num_bytes_to_read: usize, encodings_on_stack: &[(u256, u8); 256] ) -> Vec<u8> where T: Seek + Read + Sync + Send { if let Err(_) = t.seek(SeekFrom::Start(offset_from_start as u64)) { better_exit(vec!["Failed to set cursor to required byte"], EXIT_CODE_FILE_ERR); } let mut byte_vec: Vec<u8> = Vec::new(); let mut byte_buf = vec![0; num_bytes_to_read]; let mut bit_container = BitContainer::new(); let mut last_byte_bitmask = 0xFF; let mut tot_bytes_read = 0; // 从`t`读取并压缩`num_bytes_to_read`字节的逻辑 // 因代码量较大且非必要,此处省略 byte_vec }
调用encode_segment的线程闭包
// 调用encode_segment的线程创建与闭包 let thread_spawn = thread::Builder::new().spawn(move || { let mut buf_for_file = BufReader::with_capacity( MAX_SEGMENT_SIZE, open_file(&in_path_ptr_cl.read().unwrap()) ); let stk_enc_rwl = match stk_enc_ptr_cl.read() { Ok(nested) => nested, Err(_) => better_exit( vec!["`RwLock` containing `stk_enc_ptr_cl` is poisoned"], EXIT_CODE_DEV_ERR ), }; // 较慢的实现未使用encode_segment // 而是将encode_segment内的逻辑直接写在此闭包中 let bytes = encode_segment( &mut buf_for_file, seek, workload, &stk_enc_rwl ); if let Err(_) = sndr_cl.send((i, bytes)) { better_exit( vec!["`rcvr` dropped before `sndr` clone(s) could finish"], EXIT_CODE_DEV_ERR ); } });
编译配置
我调整过优化级别,发现opt-level=2比3生成的二进制运行更快,但不管用哪种优化级别,性能差异始终存在。我的release配置如下:
[profile.release] opt-level = 2 debug = false split-debuginfo = 'packed' lto = 'fat' panic = 'abort'
疑问与需求
我考虑过用rayon,但更倾向于只用Rust标准库。现在困惑的是:为什么仅仅把闭包内的逻辑提取成独立函数,就能带来这么大的性能提升?另外我还在学习Rust,欢迎各位给出编程建议。
内容的提问来源于stack exchange,提问作者keezin
相关产品推荐
相关产品推荐

