C++文本文件读取性能

6

我正在尝试将一个C#程序迁移到C++。 该C#程序逐行读取一个大小为1 ~ 5 GB的文本文件,并对每一行进行一些分析。 以下是C#代码。

using (var f = File.OpenRead(fname))
using (var reader = new StreamReader(f))
    while (!reader.EndOfStream) {
        var line = reader.ReadLine();
        // do some analysis
    }

对于一个包含700万行的1.6GB文件,该代码大约需要18秒钟。
我首先编写的用于迁移的C++代码如下:
ifstream f(fname);
string line;    
while (getline(f, line)) {
    // do some analysis
}

上面的c++代码大约需要420秒。我写的第二个c++代码如下所示。
ifstream f(fname);
char line[2000];
while (f.getline(line, 2000)) {
    // do some analysis
}

上述的C++代码大约需要85秒时间。

我尝试的最后一段代码是C语言,如下所示:

FILE *file = fopen ( fname, "r" );
char line[2000];
while (fgets(line, 2000, file) != NULL ) {
    // do some analysis
}
fclose ( file );

以上的c代码需要大约33秒。

最后两个代码将行解析为char[]而不是字符串,需要额外30秒将char[]转换为字符串。

是否有一种方法可以提高C/C++代码的性能,逐行读取文本文件以匹配C#的性能? (添加:我使用的是Windows 7 64位操作系统,VC++ 10.0,x64)


你的问题类似于这个帖子:http://stackoverflow.com/questions/7102087/how-to-enhance-the-speed-of-my-c-program-in-reading-delimited-text-files/7102179#7102179 - Constantine Samoilenko
1
一个有趣的问题是:C# 是如何做到的?这将为您提供一些信息,了解他们使用了哪些优化,并可能建议一些。 - ssube
3个回答

9
使用内存映射文件(在Unix上使用mmap(),在Windows上使用CreateFileMapping()等)是提高文件读取性能最好的方法之一。这样,您的文件就会出现在内存中作为一个平坦的字节块,您可以比使用缓冲I/O更快地读取它。
对于大于1 GB左右的文件,您将需要使用64位操作系统(带有64位进程)。我用Python处理了一个30 GB的文件并取得了出色的结果。

0
我建议两件事情:
使用 f.rdbuf()->pubsetbuf(...) 来设置更大的读取缓冲区。当使用更大的缓冲区大小时,我注意到fstream性能有了显著提高。
不要使用 getline(...),而是使用 read(...) 读取更大的数据块并手动解析它们。

0

使用优化编译。C++ 有相当多的理论开销,优化器会将其删除。例如,许多简单的字符串方法将被内联。这可能是为什么你的 char[2000] 版本更快的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接