为什么 BufReader 实际上不会缓冲短查找?

use*_*312 2 rust

我的应用程序使用一个非常大的文件,并从小窗口内的各种偏移量执行许多非常小的读取。我将直接文件读取替换为通过BufReader. 然后我使用进程监视器(来自 Sysinternals 套件)检查了操作系统执行的实际读取内容,似乎根本没有缓冲任何内容。更糟糕的是,它现在每次都会读取整个缓冲区容量,这使得性能变得更糟。

复制:

use std::fs::File;
use std::io::{BufReader, Read, Seek, SeekFrom};

fn main() {
    let path = "data.bin";
    let f = File::open(path).unwrap();
    let mut r = BufReader::with_capacity(8 * 1024, f);

    let mut buf = [0; 8];

    r.seek(SeekFrom::Start(0)).unwrap();
    r.read(&mut buf).unwrap();

    r.seek(SeekFrom::Start(100)).unwrap();
    r.read(&mut buf).unwrap();

    r.seek(SeekFrom::Start(200)).unwrap();
    r.read(&mut buf).unwrap();
}
Run Code Online (Sandbox Code Playgroud)

BufReader像这样的场景我该如何使用呢?

Mat*_* M. 5

这是通过Seek::seekfor的实现调用的BufReader

\n
\n

在底层读取器中查找偏移量(以字节为单位)。

\n

用于查找的位置是如果没有内部缓冲区SeekFrom::Current(_)则底层读取器所在的位置。BufReader<R>

\n

查找始终会丢弃内部缓冲区,即使查找位置\n落入其中。这保证了BufReader::into_inner()在查找后立即调用\n 会在同一位置产生底层读取器。

\n

要在不丢弃内部缓冲区的情况下进行查找,请使用\n BufReader::seek_relative

\n

请参阅std::io::Seek了解更多详情。

\n

注意:在边缘情况下,\xe2\x80\x99 正在使用SeekFrom::Current(n)n 进行查找,其中 n 减去内部缓冲区长度会溢出 i64,\n 将执行两次查找而不是一次。如果第二次查找返回 Err,则\n底层读取器将保留在与\n您使用以下命令调用查找时相同的位置:SeekFrom::Current(0)

\n
\n

推理已列出,并提供了您的用例的解决方法......具体来说,请致电BufReader::seek_relative

\n
\n

相对于当前位置进行查找。如果新位置位于缓冲区内,则缓冲区将不会被刷新,从而允许更有效的查找。此方法不会返回底层读取器的位置,因此调用者必须在需要时自行跟踪此信息。

\n
\n