Jos*_*ers -1 c++ performance file-io
所以,我尝试过这个:
uint64_t size = 1 * 1000 * 1000 * 1000;
std::vector<char> data(size, 'a');
std::ofstream myfile;
myfile.open("test.dat");
for (auto it = data.begin(); it != data.end(); ++it)
{
myfile << *it;
}
myfile.close();
Run Code Online (Sandbox Code Playgroud)
它可以工作,但需要 15 分钟以上的时间才能发布。我运行的是 1TB NVME SSD 和 64GB RAM,我觉得我应该能够在几秒钟或不到一秒内完成此操作。
我确实可以访问 C++20。我更喜欢现代的东西,因为它具有可读性,只要它具有合理的性能。我觉得超过10秒就太慢了。
需要明确的是,将所有数据推回数组几乎是即时的。但写下来只需要几分钟的时间。
一次写入一个字节会导致很高的开销,特别是当文件未缓冲并且您要为每个字节进行系统调用时。同样,operator<<写入格式化数据,这对于 char 来说是正确的,但更容易出错,因为许多输入在写入过程中会被格式化。
相反,您已经可以访问充满的缓冲区char- 最简单的解决方案是使用以下命令写入整个缓冲区ofstream::write:
#include <vector>
#include <iostream>
#include <fstream>
int main()
{
uint64_t size = 2 * 1000 *1000 * 1000;
std::vector<char> data;
data.reserve(size);
for (int i = 0; i < size; ++i)
{
data.push_back('a');
}
std::ofstream myfile;
myfile.open("test.dat");
myfile.write(data.data(), size);
myfile.close();
}
Run Code Online (Sandbox Code Playgroud)
当straced时,上面的例子只使用了一个系统调用来写:
writev(3, [{iov_base=NULL, iov_len=0}, {iov_base="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., iov_len=2000000000}], 2) = 2000000000
Run Code Online (Sandbox Code Playgroud)
更好的是,写入(例如)1 MB 块 1000 次,以避免分配一整 GB 的 RAM:
#include <vector>
#include <iostream>
#include <fstream>
int main()
{
uint64_t size = 1000 * 1000;
std::vector<char> data;
data.reserve(size);
for (int i = 0; i < size; ++i)
{
data.push_back('a');
}
std::ofstream myfile;
myfile.open("test.dat");
for (int i = 0; i < 1000; i++) {
myfile.write(data.data(), size);
}
myfile.close();
}
Run Code Online (Sandbox Code Playgroud)
最后,请注意您要放入缓冲区的内容。\bais 是一个多字节字符 -是and is\b的转义。在我的机器上,这被截断为. 如果您希望文件中包含更多有趣的数据,请更改填充缓冲区的循环。0x08aaa