问题描述
在逐行读取文本文件时,我注意到使用 C++ std::getline
与使用 GCC 4.8.5 的 C 函数 getline
相比性能显着下降。
我将我的测试限制在一个计算行数的非常简单的程序中。
在 C++ 中:
#include <iostream>
#include <string>
using namespace std;
int main() {
size_t n = 0;
string line;
while (getline(cin,line)) ++n;
cout << n << endl;
return 0;
}
在 C:
#include <stdio.h>
#include <stdlib.h>
int main() {
size_t n = 0;
char* line = NULL;
size_t len = 0;
while (getline(&line,&len,stdin) != -1) ++n;
printf("%zu\n",n);
free(line);
return 0;
}
在这两种情况下,我都使用 C++ 编译器来确保差异完全来自 getline
而不是来自 C 与 C++ 编译器优化。
“仅”几千行后,我开始注意到性能下降。
具有 ~600、2.5k、20k、157k、10M、40M、50M、60M 和 80M 线的示例:
Nb lines | Time (C) | Time (C++) | slower
----------+------------+------------+--------
613 | 0m0.003s | 0m0.005s | 1.5x
2452 | 0m0.002s | 0m0.011s | 5.5x
19616 | 0m0.004s | 0m0.062s | 15x
156928 | 0m0.014s | 0m0.511s | 37x
10043392 | 0m0.776s | 0m31.560s | 41x
40173568 | 0m3.335s | 2m7.752s | 38x
50216960 | 0m5.543s | 2m42.116s | 18x
60260352 | 0m22.571s | 3m13.148s | 9x
80347136 | 0m27.713s | 4m18.272s | 9x
这些数字应该加一点盐,但我认为它们反映了值如何随着文件大小的增加而增加,并且在事情开始略微平衡之前有某种最大值大约慢了 40 左右,这可能是由于其他限制(可能是硬件?)而不是软件问题。
考虑到我几乎只读取 100k+ 行的文件,如果我坚持使用 C++ 代码,我应该期望性能下降 9 倍(最多)。
有这么大的差异的原因吗?我知道 STL 开销可能很大,但我认为文件访问会超过这些差异。
另外,有没有一种方法可以优化对 std::getline
的调用(显然,除了使用它的 C 语言之外)?
附加说明
- 我尝试了 GCC 9.3.0 并得到了类似的结果
- 我尝试了一些编译器优化,但没有发现显着改进,构建/测试调用是:
gcc -c count.cpp && gcc -o count count.o && (time ./count < infile)
- 根据@Eljay 的建议,我在 C++ 代码的开头添加了
ios_base::sync_with_stdio(false);
和cin.tie(NULL);
,结果要好得多,尽管与 C 代码不完全相同;在平衡性能与可读性方面仍然可以接受(注意:这个隔离的代码在 C 和 C++ 中都可读,但完整的代码在 C++ 中更具可读性)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)