這幾天在寫一個linux下的統計程序,主要是將一個文本文件讀取后,按行進行分類統計.
用C++加 Stl實現,在windows平臺下用vc編寫,然后上傳到linux機器上用gcc編譯.
在處理上,我用了一個list<string>作為讀取行的緩沖,讀了一定的行數后就進行處理.
在讀取文件的函數中是這樣寫的.
while (!infile.eof()) {
memset(buf, 0, sizeof(char)*2048);
infile.getline(buf, 2048);
tt = buf;
if (tt.length()) {
log_list.push_back(tt);
}
//if the file is too big, so we do statistic per 5000 lines
if (log_list.size() >= 5000) {
line_statistic(result, log_list);
log_list.clear();
}
}
一切ok, 但是這幾天要處理的文件變地很大,有100多M,我沒有多想,隨便的把
if (log_list.size() >= 5000) {
改成了
if (log_list.size() >= 50000) {
想在50000行后再進行計算處理.不料想,在linux下運行效率居然出奇的慢.
原先統計5萬行大概要20秒左右,現在居然要2分多.應該是list::size()這個函數出了問題.
我以前看過vc中的list的實現,是用一個成員變量進行記數的,在size()中就直接返回這個
值,應該不會有問題.
接著我看了gcc使用的stl的list::size()的實現,它是用
std::distance(begin(), end())
來計算的.
但是在std::distance的實現中,它按照iterator類型的不同,實現的方式也不同.
而list的iterator,是屬于雙向iterator,而非隨機iterator,因此,在std::distance()
中使用了一個循環來計算值.也就是說在gcc的stl庫中,每次調用list::size()函數,它都會從頭
到尾遍歷一遍.再看看我的代碼,循環里面每一步size()都要遍歷一遍list,難怪會變得
如此的慢.
沒想到stl的不同實現還會有這種陷阱,一不留神就撞上了.
總之 gcc中list的size()是不能隨便用的,list越大,size()函數花的時間越長.