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

Performance Difference Between C and C++ Style File IO

我一直听说C++文件I/O操作要比C样式I/O慢得多,但是我没有发现任何实际的引用,它们比较慢,所以我决定在我的机器上测试它(Ubuntu 12.04,GCC 4.63,Ext4分区格式)。

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

C++(ofstream):163S

1
2
3
4
ofstream file("test.txt");

for(register int i = 0; i < 100000000; i++)
    file << i << endl;

C(fprintf:12秒

1
2
3
4
5
FILE *fp = fopen("test.txt","w");

for(register int i = 0; i < 100000000; i++)
    fprintf(fp,"%d
"
, i);

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

C++(ifstream):12S

1
2
3
4
5
int n;
ifstream file("test.txt");

for(register int i = 0; i < 100000000; i++)
    file >> n;

C(fscanf:12秒

1
2
3
4
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 << ' ';已将运行时间从163秒缩短到16s。


你用endl来打印新行。这就是问题所在,因为它不仅仅打印新行&mdash;endl还刷新缓冲区,这是一个昂贵的操作(如果在每次迭代中都这样做的话)。

如果您的意思是:

1
2
file << i << '
'
;

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


不,C++的输入/输出并不比C的慢很多——如果有的话,一个现代的实现应该在格式化的输入/输出上稍微快一些,因为它不需要解析一个格式字符串,而格式化是通过编译流操作符的链接在编译时确定的。

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

  • 使用完全优化(-O3进行编译,以获得公平的比较。
  • 一个适当的基准需要估计偏差——在实践中,这意味着你需要重复你的测试并交错它们。目前,您的代码对来自后台进程的干扰不具有鲁棒性。您还应该报告重复运行的摘要统计信息,以捕获歪曲估计的异常值。
  • 禁用C流与C流的同步(EDOCX1,4)
  • '
    '
    代替(冲洗)std::endl
  • 不要使用register声明——它只是没有任何区别,现代编译器可能会忽略它。


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

相反,禁用流缓冲会显著降低性能。在没有设置缓冲区的情况下,至少MSVC 2015实现一次将1个字符复制到filebuf(参见streambuf::xsputn),这会使应用程序受到CPU限制,从而降低I/O速率。

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

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