为何Rust读取TSV文件性能不及Python?求问题排查
TSV文件处理:Rust实现性能不如Python的疑问
我有一个TSV文件,其中有多行以#开头的注释行。文件包含多列,但我只需要第0列和第2列,且这两列存在重复数据,需要尽量去重。
Python实现及性能
实现该功能的Python函数如下,经timeit测试执行时间为1.74s:
def read_faulty_tsv(path): # 1.74 s ± 18.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) with open(path) as _f: i = 0 header = None for line in _f.readlines(): if line.startswith("#"): i += 1 else: break data = pd.read_csv(path, sep="\t", skiprows=i, header=None) data = data.drop_duplicates([0,2]) return data
注:第0列和第2列存在关联(如第0列是X,第2列是2X),因此可优化为仅按第0列去重,优化后性能基本不变(约1.86s)。
Rust实现及性能
我用Rust实现了两个类似功能的函数:一个使用原生方法,另一个使用csv crate(版本1.1)。未开启--release时,两个函数分别耗时5.260s和7.729s,远慢于Python;开启--release后,耗时降至2.486s和3.971s,但仍比Python慢。
使用csv crate的实现
use csv::ReaderBuilder; use std::time::Instant; use std::io::{BufRead, BufReader}; use std::fs::File; use std::error::Error; use std::collections::{HashSet,HashMap}; use std::path::PathBuf; fn read_fault_tsv(file_path:&PathBuf)->Result<HashMap<u32,u32>, Box<dyn Error>>{ let mut final_labels: HashMap<u32, u32> = HashMap::new(); let file = File::open(file_path)?; let reader = BufReader::new(file); // Create a vector to store non-comment lines let mut lines = Vec::new(); let start_time = Instant::now(); // Read lines and skip comment lines for line in reader.lines() { let line = line?; if !line.starts_with('#') { lines.push(line); } } let joined_lines = lines.join("\n"); // Create a CSV reader with tab delimiter from the collected lines let mut rdr = ReaderBuilder::new() .delimiter(b'\t') .from_reader(joined_lines.as_bytes()); for result in rdr.records(){ match result { Ok(record)=>{ let first_c = record[0].parse::<u32>().unwrap(); if !final_labels.contains_key(&first_c){ let third_c = record[0].parse::<u32>().unwrap(); final_labels.insert(first_c,third_c); } } Err(e) => { eprintln!("Error -- {}",e) } } } let elapsed_time = start_time.elapsed(); println!("Elapsed time: {}.{:03} seconds", elapsed_time.as_secs(), elapsed_time.subsec_millis()); Ok(final_labels) }
原生方法实现
fn read_fault_tsv2(file_path:&PathBuf)->Result<HashMap<u32,u32>, Box<dyn Error>>{ let mut final_labels: HashMap<u32, u32> = HashMap::new(); let file = File::open(file_path)?; let reader = BufReader::new(file); let lines = reader.lines() .filter_map(Result::ok) .filter(|line|!line.starts_with('#')); let start_time = Instant::now(); for line in lines{ let columns: Vec<&str> = line.split('\t').collect(); if columns.len() > 2 { if let Ok(key) = columns[0].parse::<u32>() { if !final_labels.contains_key(&key) { if let Ok(value) = columns[2].parse::<u32>() { final_labels.insert(key, value); } } } } }; let elapsed_time = start_time.elapsed(); println!("Elapsed time: {}.{:03} seconds", elapsed_time.as_secs(), elapsed_time.subsec_millis()); Ok(final_labels) }
疑问
请问我是否在实现中存在严重问题,导致Python性能超过Rust?
内容的提问来源于stack exchange,提问作者ivan199415
相关产品推荐
相关产品推荐

