这几天在写一个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()函数花的时间越长.