在Rust中迭代文件字节的更快方法是什么?
我是 Rust 的新手,我正在尝试想出一个简单的备份程序。第一步,文件被分解成可变长度的块(通过内容定义的分块)。
为此,我必须逐字节读取文件。不幸的是,我发现这个过程非常缓慢。随着dd我能够以高达350 MIB读取/秒。尽管如此,使用以下 Rust 代码我只能得到大约 45 MiB/s。(我省略了那里的所有分块内容。)
我正在阅读的文件大小约为 7.7 GiB。
// main.rs
use std::fs::File;
use std::io::BufReader;
use std::io::{Read, Bytes};
use std::time::{Instant, Duration};
fn main() {
let file = File::open("something_big.tar").expect("Cannot read file.");
let mut buf = BufReader::new(file);
let mut x = 0u8;
let mut num_bytes = 0usize;
let t1 = Instant::now();
for b in buf.bytes() {
match b {
Ok(b) => {
x += b;
num_bytes += 1;
// chunking stuff omitted
},
Err(_) => panic!("I/O Error")
}
}
let dur = t1.elapsed().as_secs_f64();
let mut num_bytes = (num_bytes as f64) / 1_048_576f64;
println!("RESULT: {}", x);
println!("Read speed: {:.1} MiB / s", num_bytes / dur);
}
问题:使用 Rust快速迭代文件字节的更好方法是什么?我的代码有什么问题?
我知道也许我可以使用memmap板条箱或类似的东西——但是:我不想那样做。
回答
我不确定为什么会发生这种情况,但是read()从BufReader. 使用下面的 512 字节数组,我看到 ~2700MiB/s,单字节数组约为 300 MiB/s。
该Bytes迭代器显然引起一些开销,这种实现是或多或少复制其粘贴IntoIterator实现。
use std::fs::File;
use std::io::{BufReader, ErrorKind};
use std::io::Read;
use std::time::Instant;
fn main() {
let file = File::open("some-3.3gb-file")
.expect("Cannot read file.");
let mut buf = BufReader::new(file);
let mut x = 0u8;
let mut num_bytes = 0usize;
let t1 = Instant::now();
let mut bytes = [0; 512];
loop {
match buf.read(&mut bytes) {
Ok(0) => break,
Ok(n) => {
for i in 0..n {
num_bytes += 1;
x += bytes[i];
}
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => panic!("{:?}", e),
};
}
let dur = t1.elapsed().as_secs_f64();
let mut num_bytes = (num_bytes as f64) / 1_048_576f64;
println!("RESULT: {}", x);
println!("Read speed: {:.1} MiB / s for {}", num_bytes / dur, num_bytes);
}