c++文本文件读取性能

本文关键字:性能 读取 文件 文本 c++ | 更新日期: 2023-09-27 18:06:28

我正在尝试将c#程序迁移到c++。c#程序逐行读取1~ 5gb大小的文本文件,并对每行进行一些分析。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.6 gb的文件,这段代码大约需要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[]而不是字符串,将char[]转换为字符串需要大约30秒。

是否有一种方法可以提高c/c++代码的性能来逐行读取文本文件以匹配c#性能?(补充:我使用windows 7 64位操作系统与vc++ 10.0, x64)

c++文本文件读取性能

提高文件读取性能的最佳方法之一是使用内存映射文件(Unix上的mmap(), Windows上的CreateFileMapping()等)。然后你的文件在内存中显示为一个平坦的字节块,你可以读它比做缓冲I/o快得多。

对于大于1 gb左右的文件,您将希望使用64位操作系统(带有64位进程)。我已经用Python处理了一个30gb的文件,效果非常好。

我建议两件事:

使用f.rdbuf()->pubsetbuf(...)设置更大的读缓冲区。我注意到当使用更大的缓冲区时,fstream性能有了一些非常显著的提高。

代替getline(...)使用read(...)读取更大的数据块并手动解析它们

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