getline 在 C++ 中比 C

问题描述

在逐行读取文本文件时,我注意到使用 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 (将#修改为@)