使用istream和FILE进行getline的性能差异*

时间:2017-07-30 13:40:45

标签: c++ ifstream getline

我正在尝试逐行比较读取文件的性能。第一种情况是getline for string和istream,第二种情况是getline for char *和FILE *。我想知道:

  1. 为什么第一个案例是如此缓慢
  2. 是否可以更快地使C ++代码段
  3. 考虑下面的输出(ifstream first):

    Lines count: 10628126
    ifstream getline: 43.2684
    Lines count: 10628126
    fopen getline: 1.06217
    

    FILE * first:

    Lines count: 10628126
    fopen getline: 1.96065
    Lines count: 10628126
    ifstream getline: 43.0428
    

    我用于测试的代码:

    #include <fstream>
    #include <iostream>
    #include <string>
    
    #include <sys/time.h>
    #include <stdio.h>
    
    
    using namespace std;
    
    double gettime()
    {
        double result = 0;
        struct timeval tv = {0};
        struct timezone tz = {0};
        gettimeofday(&tv, &tz);
        result = tv.tv_sec + (1.0 * tv.tv_usec / 1000000);
        return result;
    }
    
    void read_cpp(const char * filename)
    {
        ifstream ifile(filename);
        string line;
        unsigned int i = 0;
        while(getline(ifile, line)) i++;
        cout << "Lines count: " << i << endl;
    }
    
    void read_c(const char * filename)
    {
        FILE * ifile = fopen(filename, "r");
        size_t linesz = 4096+1;
        char * line = new char[linesz];
        unsigned int i = 0;
        while(getline(&line, &linesz, ifile) > 0) i++;
        delete[] line;
        cout << "Lines count: " << i << endl;
        fclose(ifile);
    }
    
    int main(int argc, char * argv[])
    {
        double tmstart;
        tmstart = gettime();
        read_cpp(argv[1]);
        cout << "ifstream getline: " << (gettime() - tmstart) << endl;
        tmstart = gettime();
        read_c(argv[1]);
        cout << "fopen getline: " << (gettime() - tmstart) << endl;
    }
    

    P.S。我尝试交换read_cpp和read_c几乎没有差别。

    更新

    看起来@Galik和@geza无法使用g ++编译器重现问题,所以我检查了linux环境下的代码, C C ++之间几乎没有区别< / strong>实施。所以这似乎是一个环境问题。最初我使用Mac OS X和默认的C ++编译器测量时间clang(对我来说很惊讶):

    $ g++ -v
    Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
    Apple LLVM version 8.1.0 (clang-802.0.42)
    Target: x86_64-apple-darwin16.7.0
    Thread model: posix
    InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
    

    但所有这些事情从未发生过真正的g++

    $ g++ -v
    Using built-in specs.
    COLLECT_GCC=g++
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
    Target: x86_64-linux-gnu
    Configured with: ...
    Thread model: posix
    gcc version 4.9.2 (Debian 4.9.2-10)
    

    很抱歉给您带来不便。

    UPDATE2

    我找到了相关主题clang++ fstreams 10X slower than g++。作者还面临clang编译的代码的性能下降。要解决此问题,可以使用不同的stdlib实施(-stdlib=stdlibc++)而不是默认的-stdlib=libc++)。在这种情况下,clang将显示弃用警告:

    clang: warning: libstdc++ is deprecated; move to libc++ [-Wdeprecated]
    

    但性能会更好(即使没有优化):

    Lines count: 10628126
    fopen getline: 1.02899
    Lines count: 10628126
    ifstream getline: 1.67594
    

1 个答案:

答案 0 :(得分:1)

c ++版本执行更多边界检查,区域设置解释和iostream状态管理。它非常强大。

c版本极简主义且更加脆弱。

安全和实用是有代价的。

那个价格就是时间。

更新

c readline期望使用malloc和free,而不是new和delete。

以下是更正后的版本:

#include <cstdlib>
#include <cstdio>
#include <iostream>

void read_c(const char * filename)
{
    FILE * ifile = fopen(filename, "r");
    size_t linesz = 0;
    char * line = nullptr;
    unsigned int i = 0;
    while(getline(&line, &linesz, ifile) > 0) i++;
    free(line);
    std::cout << "Lines count: " << i << std::endl;
    fclose(ifile);
}