gpt4 book ai didi

c++ - 在 C++ : strange performance issue 中读取文件的奇特方式

转载 作者:可可西里 更新时间:2023-11-01 16:37:08 28 4
gpt4 key购买 nike

在 C++ 中读取文件的常用方法是这样的:

std::ifstream file("file.txt", std::ios::binary | std::ios::ate);
std::vector<char> data(file.tellg());
file.seekg(0, std::ios::beg);
file.read(data.data(), data.size());

读取 1.6 MB 的文件几乎是即时的。

但是最近,我发现std::istream_iterator并想尝试一下,以便编写一种漂亮的单行方式来读取文件内容。像这样:

std::vector<char> data(std::istream_iterator<char>(std::ifstream("file.txt", std::ios::binary)), std::istream_iterator<char>());

代码很好,但是非常慢。读取相同的 1.6 MB 文件大约需要 2/3 秒。我知道这可能不是读取文件的最佳方式,但为什么它这么慢?

以经典方式读取文件是这样的(我只谈论读取函数):

  • istream 包含一个 filebuf其中包含来自文件的数据 block
  • 读取函数调用sgetn来自 filebuf,它将字符从内部缓冲区一个一个地(无 memcpy)复制到“数据”的缓冲区
  • 当filebuf中的数据被完全读取时,filebuf从文件中读取下一个 block

当您使用 istream_iterator 读取文件时,它是这样的:

  • vector 调用 *iterator 来获取下一个字符(这只是读取一个变量),将其添加到末尾并增加其自身的大小
  • 如果 vector 的分配空间已满(这种情况并不经常发生),则执行重定位
  • 然后它调用++iterator 从流中读取下一个字符(运算符 >> 带有一个 char 参数,它当然只是调用 filebuf 的 sbumpc 函数)
  • 最后比较迭代器和结束迭代器,这是通过比较两个指针来完成的

我必须承认,第二种方式效率不高,但至少比第一种方式慢200倍,这怎么可能?

我认为性能 killer 是重定位或插入,但我尝试创建一个完整的 vector 并调用 std::copy,它同样慢。

// also very slow:
std::vector<char> data2(1730608);
std::copy(std::istream_iterator<char>(std::ifstream("file.txt", std::ios::binary)), std::istream_iterator<char>(), data2.begin());

最佳答案

您应该逐一比较。

您的第一个代码读取了未格式化 二进制数据,因为您使用了函数成员“read”。并不是因为您顺便使用了 std::ios_binary,请参阅 http://stdcxx.apache.org/doc/stdlibug/30-4.html更多解释,但简而言之:“二进制打开模式的效果经常被误解。它不会将插入器和提取器置于二进制模式,因此会抑制它们通常执行的格式。二进制输入和输出完全由basic_istream<>::read() 和 basic_ostream<>::write()"

因此,您的第二个带有 istream_iterator 的代码会读取格式化 文本。它要慢得多。

如果你想读取未格式化的二进制数据,使用istreambuf_iterator:

#include <fstream>
#include <vector>
#include <iterator>

std::ifstream file( "file.txt", std::ios::binary);
std::vector<char> buffer((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());

在我的平台 (VS2008) 上,istream_iterator 比 read() 慢 100 倍。 istreambuf_iterator 性能更好,但仍然比 read() 慢 10 倍。

关于c++ - 在 C++ : strange performance issue 中读取文件的奇特方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3311509/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com