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

Raf*_*mal 24 c c++ file-io stream

我一直听说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;
Run Code Online (Sandbox Code Playgroud)

C(fprintf):12s

FILE *fp = fopen("test.txt", "w");

for(register int i = 0; i < 100000000; i++) 
    fprintf(fp, "%d\n", i);
Run Code Online (Sandbox Code Playgroud)

我期待这样的输出,它表明在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;
Run Code Online (Sandbox Code Playgroud)

C(fscanf):12s

FILE *fp = fopen("test.txt", "r");

for(register int i = 0; i < 100000000; i++) 
    fscanf(fp, "%d", &n);
Run Code Online (Sandbox Code Playgroud)

那么,为什么花这么长时间用流执行写作呢?或者,与写作相比,为什么使用流阅读速度如此之快?

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

Naw*_*waz 29

您正在使用endl打印换行符.这是这里的问题,因为它不仅仅是打印一个换行符- endl刷新这是一个昂贵的操作缓冲区(如果你这样做,在每次迭代).

使用\n,如果你的意思是这样:

file << i << '\n';
Run Code Online (Sandbox Code Playgroud)

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

  • 那么实际上没有"C和C++样式文件IO之间的性能差异"? (3认同)
  • 谢谢,这就是问题所在。更改为 '\n' 将时间减少到 16 秒! (2认同)
  • @AlexandruBarbarosie:是的,没有理由. (2认同)

Kon*_*lph 21

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

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

  • 使用完全优化(-O3)进行编译以获得公平的比较.
  • 适当的基准需要估计偏差 - 实际上这意味着您需要重复测试并交错.目前,您的代码对后台进程的干扰不稳健.您还应该报告重复运行的摘要统计信息,以捕获扭曲估计值的异常值.
  • 使用C流禁用C++流同步(std::ios_base::sync_with_stdio(false);)
  • '\n'而不是(冲洗)std::endl
  • 不要使用register声明 - 它根本没有区别,现代编译器可能无论如何都会忽略它.