为什么 ifstream::read 比使用迭代器快得多

Why is ifstream::read much faster than using iterators?

本文关键字:迭代器 快得多 ifstream read 为什么      更新时间:2023-10-16

实际上,有许多方法可以将文件读入字符串。两个常见的是使用 ifstream::read 直接读取字符串和使用 steambuf_iterators 和 std::copy_n:

使用 ifstream::read:

std::ifstream in {"./filename.txt"};
std::string contents;
in.seekg(0, in.end);
contents.resize(in.tellg());
in.seekg(0, in.beg);
in.read(&contents[0], contents.size());

使用 std::copy_n:

std::ifstream in {"./filename.txt"};
std::string contents;
in.seekg(0, in.end);
contents.resize(in.tellg());
in.seekg(0, in.beg);
std::copy_n(std::streambuf_iterator<char>(in), 
            contents.size(), 
            contents.begin();

许多基准测试表明,第一种方法比第二种方法快得多(在我的机器中使用 g++-4.9 时,使用 -O2 和 -O3 标志的速度大约快 10 倍),我想知道这种性能差异的原因可能是什么。

read是单个 iostream 设置(每个 iostream 操作的一部分)和对操作系统的单个调用,直接读取您提供的缓冲区。

迭代器的工作原理是使用 operator>> 重复提取单个char。由于缓冲区大小,这可能意味着更多的操作系统调用,但更重要的是,它还意味着重复设置和拆除iostream哨兵,这可能意味着互斥锁,通常意味着一堆其他东西。此外,operator>>是格式化操作,而read是未格式化的操作,这是每个操作的额外设置开销。

编辑:疲惫的眼睛看到istream_iterator而不是istreambuf_iterator。当然,istreambuf_iterator不做格式化输入。它在streambuf上称为sbumpc或类似的东西。仍然有很多调用,并使用缓冲区,它可能小于整个文件。