C和C++风格文件IO的性能差异

Performance Difference Between C and C++ Style File IO

本文关键字:性能 IO 文件 C++ 风格      更新时间:2023-10-16

我一直听说C++文件I/O操作比C风格的I/O慢得多。但我没有找到任何关于它们实际速度的实用参考,所以我决定在我的机器上测试它(Ubuntu 12.04,GCC 4.6.3,ext4分区格式)。

首先,我在磁盘中写了一个~900MB的文件。

C++(ofstream):163s

ofstream file("test.txt");
    
for(register int i = 0; i < 100000000; i++) 
    file << i << endl;

C(fprintf):12s

FILE *fp = fopen("test.txt", "w");
    
for(register int i = 0; i < 100000000; i++) 
    fprintf(fp, "%dn", i);

我期待着这样的输出,它表明在C++中写入文件比在C中慢得多。然后我使用C和C++I/O读取相同的文件。让我惊呼的是,在读取文件时,性能几乎并没有差别。

C++(ifstream):12s

int n;
ifstream file("test.txt");
for(register int i = 0; i < 100000000; i++) 
    file >> n;

C(fscanf):12s

FILE *fp = fopen("test.txt", "r");
    
for(register int i = 0; i < 100000000; i++) 
    fscanf(fp, "%d", &n);

那个么,为什么使用流执行写操作要花这么长时间呢?或者,为什么使用流式阅读比写作快?

结论:正如答案和评论所指出的,罪魁祸首是std::endl。更改线路file << i << endl;file << i << 'n';将运行时间从163s缩短到16s。

您正在使用endl打印新行。这就是问题所在,因为它所做的比打印换行符更多endl刷新缓冲区,这是一个昂贵的操作(如果您在每次迭代中都这样做)。

如果你是认真的话,使用n

file << i << 'n';

此外,必须在发布模式下编译代码(即打开优化)。

不,C++输入/输出并不比C的慢——如果有什么不同的话,现代实现在格式化输入/输出方面应该稍微快一点,因为它不需要解析格式字符串,而是在编译时通过流运算符的链接来确定格式。

以下是在基准测试中需要考虑的几个注意事项:

  • 使用完全优化编译(-O3)以获得公平的比较
  • 一个合适的基准需要估计偏差——在实践中,这意味着你需要重复你的测试并将它们交错。目前,您的代码对来自后台进程的干扰并不健壮。您还应该报告重复运行的汇总统计数据,以捕捉扭曲估计的异常值
  • 禁用C++流与C流的同步(std::ios_base::sync_with_stdio(false);
  • 使用'n'而不是(冲洗)std::endl
  • 不要使用register声明——这根本没有什么区别,而且现代编译器可能会忽略它

使用fstream处理大文件时,请确保设置流缓冲区>0

与直觉相反,禁用流缓冲会显著降低性能。至少MSVC;2015实现在未设置缓冲区时,将1个字符一次复制到filebuf(请参阅streambuf::xsputn),这可能会使应用程序CPU受限,从而降低I/O速率。

const size_t bufsize = 256*1024;
char buf[bufsize];
mystream.rdbuf()->pubsetbuf(buf, bufsize);

您可以在这里找到完整的示例应用程序。