簡體   English   中英

在C ++中按行讀取大文件

[英]Read a big file by lines in C++

我有一個將近800M的大文件,我想逐行閱讀。

首先,我使用Python編寫程序,使用linecache.getline:

lines = linecache.getlines(fname)

費用約為1.2秒。

現在,我想將程序移植到C ++。

我寫了這些代碼:

    std::ifstream DATA(fname);
    std::string line;
    vector<string> lines;

    while (std::getline(DATA, line)){
        lines.push_back(line);
    }

但這很慢(花費幾分鍾)。 如何改善呢?

  • Joachim Pileborg提到了mmap() ,並且在Windows上可以使用CreateFileMapping()

我的代碼在VS2013下運行,當我使用“ DEBUG”模式時,需要162秒。

當我使用“ RELEASE”模式時,只有7秒!

非常感謝@DietmarKühl和@Andrew

對於c ++,您可以嘗試這樣的操作:

void processData(string str)
{
  vector<string> arr;
  boost::split(arr, str, boost::is_any_of(" \n"));
  do_some_operation(arr);
}

int main()
{
 unsigned long long int read_bytes = 45 * 1024 *1024;
 const char* fname = "input.txt";
 ifstream fin(fname, ios::in);
 char* memblock;

 while(!fin.eof())
 {
    memblock = new char[read_bytes];
    fin.read(memblock, read_bytes);
    string str(memblock);
    processData(str);
    delete [] memblock;
 }
 return 0;
}

首先,您可能應該確保在啟用優化的情況下進行編譯。 對於這樣一個簡單的算法,這可能無關緊要,但這實際上取決於向量/字符串庫的實現。

正如@angew所建議的那樣, std :: ios_base :: sync_with_stdio(false)對您編寫的例程產生了很大的影響。

另一個較小的優化方法是使用lines.reserve()預先分配向量,以便push_back()不會導致大量的復制操作。 但是,如果您碰巧事先知道大概會收到多少行,這將非常有用。

使用上面建議的優化,我獲得了讀取800MB文本流的以下結果:

 20 seconds ## if average line length = 10 characters
  3 seconds ## if average line length = 100 characters
  1 second  ## if average line length = 1000 characters

如您所見,速度受每行開銷的支配。 這種開銷主要發生在std::string類內部。

就存儲分配開銷而言,任何基於存儲大量std::string都可能不是最佳選擇。 在64位系統上, std::string每個字符串至少需要16個字節的開銷。 實際上,開銷很可能會大大超過該開銷,並且您會發現內存分配(在std::string內部)成為一個嚴重的瓶頸。

為了獲得最佳的內存使用和性能,請考慮編寫自己的例程以大塊讀取文件,而不要使用getline() 然后,您可以應用類似於flyweight模式的內容,以使用自定義字符串類管理各個行的索引。

PS另一個相關因素是物理磁盤I / O,緩存可能會繞過,也可能不會繞過。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM