C和C++风格文件IO的性能差异
Performance Difference Between C and C++ Style File 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, "%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);
您可以在这里找到完整的示例应用程序。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- Seg Fault Issue C++ (file IO / getline)
- OpenMP阵列性能较差
- 递归列出所有目录中的C++与Python与Ruby的性能
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 为什么在读取文件大小时文件IO速度会发生变化
- 大小相等但成员数量不同的结构之间的性能差异
- 为什么constexpr的性能比正常表达式差
- 在类中使用随机生成器时出现性能问题
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 海湾合作委员会 ARM 性能下降
- GCC 和 Clang 代码性能的巨大差异
- 在容量内调整矢量大小时的性能影响
- Agora.io 虚幻引擎插件构建错误
- 了解算法的性能差异(如果以不同的编程语言实现)
- 未达到的情况会影响开关外壳性能
- Windows:基于事件的重叠 IO 与 IO 完成端口,实际性能
- C和C++风格文件IO的性能差异
- Linux异步IO与libaio性能问题
- c++ ostringstream改进IO性能