C++ 从磁盘写入和读取性能

C++ Performance writing and reading from disk

本文关键字:读取 性能 磁盘 C++      更新时间:2023-10-16

可能的重复项:
以C++非常快的速度编写二进制文件

我在内存中有大量无符号的 32 位整数(15 亿个条目)。我需要将它们写入文件并将它们读回主内存。

现在,我使用:

ofstream ofs;
ofs.open(filename);
for (uint64_t i = 0 ; i < 1470000000 ; i++)
ofs << integers << " " ;

ifstream ifs;
ifs.open(filename);
for (uint64_t i = 0 ; i < 1470000000 ; i++)
ifs >> integers ;

这需要几分钟才能执行。任何人都可以帮助我,有没有库方法可以更快地做到这一点?或者任何建议,以便我可以运行性能测试?谁能给我看一些简单的C++代码,这些代码使用mmap来执行上述操作(在 Linux 上)?

编辑:示例案例

#include<iostream>
#include <stdint.h>
#include <cstdio>
#include <cstdlib>
#include <sstream>
using namespace std;
main()
{
      uint32_t* ele = new uint32_t [100] ;
      for(int i = 0; i < 100 ; i++ )
      ele[i] = i ;
      for(int i = 0; i < 100 ; i++ ){
          if(ele[i] < 20)
          continue ;
          else
          // write  ele[i] to file
          ;   
      }
 for(int i = 0; i < 100 ; i++ ){
          if(ele[i] < 20)
          continue ;
          else
          // read  number from file
          // ele[i] = number * 10 ;
          ;   
      }
     std::cin.get();
}

首先要做的是确定时间的去向。格式化和解析文本并非易事,可能需要一些时间,但实际的写作和阅读也可以,考虑到大小的文件。 第二件事是确定如何"便携"数据必须是:最快的解决方案几乎可以肯定是 mmap(或其 Windows 等效项)将数组转换为文件直接,从不读写。 这不提供然而,便携式表示,甚至升级编译器可能会使数据不可读。 (对于 32 位不太可能今天的整数,但过去也发生过)。

一般来说,如果时间要用于阅读和写作,你将想使用mmap进行调查。 如果它要格式化和解析,您将需要调查某种排序二进制格式 - 这也有助于读取和写入如果它使生成的文件更小。 最简单的二进制文件格式,使用正常网络标准写入值,要求不超过:

void
writeInt( std::ostream& dest, int32_t integer )
{
    dest.put( (integer >> 24) & 0xFF );
    dest.put( (integer >> 16) & 0xFF );
    dest.put( (integer >>  8) & 0xFF );
    dest.put( (integer      ) & 0xFF );
}
int32_t
readInt( std::istream& source )
{
    int32_t results = 0;
    results  = source.get() << 24;
    results |= source.get() << 16;
    results |= source.get() <<  8;
    results |= source.get();
    return results;
}

(显然需要添加一些错误检查。

如果许多整数实际上很小,您可以尝试一些可变长度编码,例如谷歌协议中使用的编码缓冲区。 如果大多数整数都在 -64...63 范围内,这可能会导致文件只有四分之一的大小(这再次,将改善读写所需的时间)。

如果你知道大小,只需写/写一个数组。

通过对输入和输出流使用更大的缓冲区,可能会获得更好的性能:

ofstream ofs;
char * obuffer = new char[bufferSize];
ofs.rdbuf ()->pubsetbuf (obuffer, bufferSize);
ofs.open (filename);
ifstream ifs;
char * ibuffer = new char[bufferSize];
ifs.rdbuf ()->pubsetbuf (ibuffer, bufferSize);
ifs.open (filename);

此外ifs >> integers ;解析整数的相当慢的方法。尝试读取行,然后使用std::strtol()来解析它们。IME,它的速度要快得多。

如果您只想复制,则可以使用它来提高性能:

std::ifstream  input("input");
std::ofstream  output("ouptut");
output << input.rdbuf();

或者设置缓冲区大小可能会提高速度:

char cbuf[buf_size];
ifstream fin;
fin.rdbuf()->pubsetbuf(cbuf,buf_size);

我没有在我的答案中考虑长 int 问题,因为我根本不知道为什么它们会影响流性能,但我希望它无论如何都会有所帮助.