何时为I / O(C ++)构build自己的缓冲区系统?

我必须处理非常大的文本文件(2 GB),所以必须逐行读写它们。 要使用ofstream编写2300万行是非常慢的,所以在开始时,我试图加快在内存缓冲区(例如256 MB或512 MB)写入大量行的过程,然后将缓冲区写入文件。 这没有奏效,performance差不多。 我有阅读文件相同的问题。 我知道I / O操作是由STL I / O系统缓冲的,这也取决于磁盘调度策略(由操作系统pipe理,在我的情况下是Linux)。

有关如何提高性能的任何想法?

PS:我一直在考虑在程序正在处理数据时使用后台subprocess(或线程)来读/写数据块,但是我不知道(主要是在subprocess的情况下)是否值得。

一个2GB的文件是相当大的,你需要知道所有可能的瓶颈区域:

  • HDD本身
  • HDD接口(IDE / SATA / RAID / USB?)
  • 操作系统/文件系统
  • C / C ++库
  • 你的代码

我开始做一些测量:

  • 您的代码需要多长时间来读取/写入2GB文件,
  • “ dd ”命令可以以多快的速度读写磁盘? 例…

    dd if=/dev/zero bs=1024 count=2000000 of=file_2GB

  • 使用大型fwrite()/ fread()调用来写/读需要多长时间

假设您的磁盘能够以大约40Mb / s的速度读写(这可能是一个真实的数字),那么您的2GB文件的运行速度不会超过50秒。

实际需要多长时间?

嗨,罗迪,使用1.1 GB的文件和大缓冲区(128,255或512 MB)fstream读取方法大约需要43-48秒,这是使用fstream getline(逐行)相同。 CP需要将近2分钟才能复制文件。

在这种情况下,你的硬件绑定。 CP必须读和写,并且会像疯了一样在磁盘表面来回寻找。 所以它会(如你所见)比简单的“阅读”情况差两倍多。

为了提高速度,我想尝试的第一件事是更快的硬盘或SSD。

你还没有说什么磁盘接口? SATA几乎是最简单/最快的选择。 另外(明显的一点,这…)确保磁盘在物理上在您的代码正在运行的同一台机器上,否则您的网络绑定…

我也建议内存映射文件,但如果你要使用boost,我认为boost :: iostreams :: mapped_file是比boost :: interprocess更好的匹配。

也许你应该看看内存映射文件。

检查他们在这个库: Boost.Interprocess

只是一个想法,但避免使用std :: endl,因为这将强制在缓冲区满之前刷新。 使用'\ n'代替换行符。

不要用new来分配这样的缓冲区:

试试:std :: vector <>

 unsigned int buffer_size = 64 * 1024 * 1024; // 64 MB for instance. std::vector<char> data_buffer(buffer_size); _file->read(&data_buffer[0], buffer_size); 

另请阅读关于在标识符名称中使用下划线的文章: 。 注意你的代码是好的,但是。

使用getline()可能是效率低下的,因为字符串缓冲区可能需要重新调整大小,因为数据是从流缓冲区附加到它的。 您可以通过预先设定字符串的大小来提高效率:

你也可以设置iostreams缓冲区的大小为非常大或NULL(对于无缓冲)

 // Unbuffered Accesses: fstream file; file.rdbuf()->pubsetbuf(NULL,0); file.open("PLOP"); // Larger Buffer std::vector<char> buffer(64 * 1024 * 1024); fstream file; file.rdbuf()->pubsetbuf(&buffer[0],buffer.size()); file.open("PLOP"); std::string line; line.reserve(64 * 1024 * 1024); while(getline(file,line)) { // Do Stuff. } 

如果你要自己缓冲文件,那么我建议使用无缓冲的I / O进行一些测试(在你打开的文件上的setvbuf可以关闭库缓冲)。

基本上,如果你要缓冲你自己,你想禁用图书馆的缓冲,因为它只会让你痛苦。 我不知道是否有任何方法来做STL I / O,所以我建议去C级的I / O。