【发布时间】:2020-11-07 12:10:29
【问题描述】:
我有一个使用 mmap 读取的大文件。我想在每一行上做一些操作,所以我在上面调用 split() ,这给了我每一行的迭代器:
let file = File::open("myfile").unwrap();
let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };
//splitting by newline
let iter = mmap.split(|elem| elem == &b'\n');
这很好用,不会给我带来任何问题 - 运行速度非常快。
但是,当我通过迭代器时,它会跳转并且通过 for 循环大约是读取和拆分时间的 4 倍。
另外,这是不处理该行或在 for 循环内做任何事情:
for elem in iter {
//process the line
}
由于性能是一个问题 - 我觉得它能够非常快速地读取和拆分文件很奇怪,但是,当我通过迭代器时它变得非常慢。我错过了什么吗?我对生锈的了解也很有限,所以不确定我是否在做坏事。有什么可以帮助我优化这一点并让我更快的访问时间吗?
此外,并行迭代器在我的情况下并没有多大帮助 - 它们增加的开销是不值得的。
整个文件:
use memmap::MmapOptions;
use std::fs::File;
use std::time::{Duration, Instant};
fn main() {
let now = Instant::now();
let file = File::open("myfile").unwrap();
let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };
let iter = mmap.split(|elem| elem == &b'\n');
/*
for elem in iter {
//do nothing
}
*/
println!("{:?}", now.elapsed());
}
如果我取消注释 for 循环,它会变慢 4 倍。我正在使用 --release 标签构建,所以这不是问题。
【问题讨论】:
-
迭代器根本不做任何事情,除非它们被迭代。您在快速情况下测量什么?
-
Cerberus 是正确的。
.split()只是构造一个 Split 结构。迭代器是惰性的,在你真正使用它们之前什么都不做,例如在 for 循环中。