2017-07-30 75 views
1

我試圖比較逐行讀取文件的性能。第一種情況是getline for string和istream,第二種情況是getline for char *和FILE *。我想知道:使用istream和FILE運行getline的性能差異*

  1. 爲什麼第一種情況太慢了
  2. 是否有可能使C++代碼段更快

考慮輸出下面(ifstream的第一):

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

FILE *第一:

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幾乎沒有區別。

UPDATE

它看起來像@Galik和@geza無法使用G ++編譯器來重現問題,所以我查了Linux環境下的代碼,有Ç℃之間幾乎沒有差別++實現。所以這似乎是一個環境問題。本來我測量使用的是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

你嘗試調用'read_c()''之前read_cpp()'? –

+0

C++流可能會更慢,因爲窗簾後面會發生更多事情,C++ streambuf可能會更快。但是,緩存也可能在這裏工作。它可能會支付交換兩種閱讀方法,並看看是否有顯着影響表現(麥克納基斯擊敗此)。 –

+0

@MikeNakis,是的,但它實際上沒有幫助。 read_c變慢了〜1sec,而read_cpp變快了〜0.2sec。 – frist

回答

1

C++版本可以做更多的邊界檢查,現場演繹和iostream狀態管理。它非常強大。

c版本是極簡主義和更脆弱。

有一個安全和實用的價格。

那個價格就是時間。

更新:

的C readline的預計使用malloc和free,而不是新的和刪除。

這裏是修正版本:

#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); 
} 
+0

有沒有其他的方式來讀取文件的最小副作用和優化?換句話說,是否可以使用C++ STL實現read_c? – frist

+0

@frist如果覺得如果你想要的是分隔的字符串,你的版本是好的。然而,有一種方法可以使它更安全。我會發布更新。 –

+0

我不會稱C'getline()'爲脆。它只是從由換行符分隔的文件中讀取塊。另一方面,[f] scanf()'很脆弱,以至於無法使用。 –