我必须处理非常大的文本文件(2 GB),必须逐行读/写它们。使用ofstream编写2300万行非常慢,所以在开始时,我试图加快在内存缓冲区(例如256 MB或512 MB)中写入大块行的过程,然后将缓冲区写入文件。这不起作用,性能或多或少相同。我在阅读文件时遇到同样的问题。我知道I / O操作是由STL I / O系统缓冲的,这也取决于磁盘调度程序策略(由操作系统管理,在我的情况下是Linux)。
关于如何提高性能的任何想法?
PS:我一直在考虑使用后台子进程(或线程)来读取/写入数据块,而程序正在处理数据但我不知道(主要是在子进程的情况下)是否会值得。
答案 0 :(得分:10)
2GB文件非常大,您需要了解可能成为瓶颈的所有可能区域:
我首先做一些测量:
“dd”命令读取和写入磁盘的速度有多快?实施例...
dd if=/dev/zero bs=1024 count=2000000 of=file_2GB
假设您的磁盘能够以大约40Mb / s的速度进行读/写(这可能是一个真实的数字),您的2GB文件运行速度不会超过50秒。
实际上需要多长时间?
嗨Roddy,使用fstream读取方法 1.1 GB文件和大文件 它需要缓冲区(128,255或512 MB) 大约43-48秒,它是相同的 使用fstream getline(逐行)。 cp需要将近2分钟的时间来复制 文件。
在这种情况下,您的硬件绑定。 cp 必须读写,并且会在疯狂的时候在磁盘表面上来回搜索。因此,(如你所见)它将比简单的'读'案例差两倍多。
为了提高速度,我首先尝试的是更快的硬盘驱动器或SSD。
您还没有说过磁盘接口是什么? SATA几乎是最简单/最快的选择。另外(显而易见的是,这......)确保磁盘在运行代码的同一台机器上运行,否则你就是网络绑定......
答案 1 :(得分:8)
我还建议使用内存映射文件但是如果你要使用boost我认为boost::iostreams::mapped_file比boost :: interprocess更好。
答案 2 :(得分:5)
也许您应该查看内存映射文件。
在此库中查看它们:Boost.Interprocess
答案 3 :(得分:3)
只是想一想,但是避免使用std :: endl,因为这会在缓冲区满之前强制刷新。使用'\ n'代替换行符。
答案 4 :(得分:2)
不要使用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);
另请阅读using underscore in identifier names:上的文章。请注意,您的代码可以,但是。
答案 5 :(得分:1)
使用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.
}
答案 6 :(得分:0)
如果你要自己缓冲文件,那么我建议使用无缓冲的I / O进行一些测试(在你已经开启的文件上使用setvbuf可以关闭库缓冲)。
基本上,如果你要缓冲自己,你想要禁用库的缓冲,因为它只会让你感到痛苦。我不知道是否有任何方法可以为STL I / O做到这一点,所以我建议你去C级I / O.