[英]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);
}
但這很慢(花費幾分鍾)。 如何改善呢?
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.