C和C ++样式文件IO之间的性能差异

我一直听说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, "%d\n", i); 

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

C ++( ifstream ):12s

 int n; ifstream file("test.txt"); for(register int i = 0; i > 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'; 将运行时间从163秒减少到16秒。

您正在使用endl来打印换行符。 这就是问题,因为它不仅仅是打印换行符 – endl还会刷新缓冲区,这是一项昂贵的操作(如果你在每次迭代中都这样做)。

如果你这样说,请使用\n

 file << i << '\n'; 

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

不,C ++输入/输出并不比C慢 – 如果有的话,现代实现应该在格式化的输入/输出上稍快一些,因为它不需要解析格式字符串,而是在编译时确定格式化流运营商的链接。

以下是基准测试中需要考虑的一些注意事项:

  • 使用完全优化( -O3 )进行编译以获得公平的比较。
  • 一个适当的基准需要估计偏差 – 实际上这意味着你需要重复你的测试并交错它们。 目前,您的代码对后台进程的干扰不稳健。 您还应该报告重复运行的摘要统计信息,以捕获扭曲估计值的exception值。
  • 禁用与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); 

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