我必须处理非常大的文本文件(2 GB),所以必须逐行读写它们。 要使用ofstream编写2300万行是非常慢的,所以在开始时,我试图加快在内存缓冲区(例如256 MB或512 MB)写入大量行的过程,然后将缓冲区写入文件。 这没有奏效,performance差不多。 我有阅读文件相同的问题。 我知道I / O操作是由STL I / O系统缓冲的,这也取决于磁盘调度策略(由操作系统pipe理,在我的情况下是Linux)。
有关如何提高性能的任何想法?
PS:我一直在考虑在程序正在处理数据时使用后台subprocess(或线程)来读/写数据块,但是我不知道(主要是在subprocess的情况下)是否值得。
一个2GB的文件是相当大的,你需要知道所有可能的瓶颈区域:
我开始做一些测量:
“ dd ”命令可以以多快的速度读写磁盘? 例…
dd if=/dev/zero bs=1024 count=2000000 of=file_2GB
假设您的磁盘能够以大约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。