bash'while read line'效率与大文件

时间:2012-04-28 14:48:20

标签: bash performance

我正在使用while循环来处理任务,

从一个大文件中读取大约1000万行的记录。

我发现随着时间的推移,处理变得越来越慢。

我用一百万行作为模拟脚本,这揭示了问题。

但我仍然不知道为什么read命令如何工作?

seq 1000000 > seq.dat
while read s;
do
    if [ `expr $s % 50000` -eq 0 ];then
        echo -n $( expr `date +%s` - $A) ' ';
        A=`date +%s`;
    fi
done < seq.dat

终端输出时间间隔:

98 98 98 98 98 97 98 97 98 101 106 112 121 121 127 132 135 134

大约50,000行,处理速度明显变慢。

2 个答案:

答案 0 :(得分:4)

阅读是一个相对缓慢的过程,作为“学习Korn Shell”的作者points out *。 (在第7.2.2.1节之上。)还有其他程序,例如awksed已经过高度优化,可以执行基本相同的操作:一次从一行文件中读取并使用该输入执行一些操作。

更不用说,每次进行减法或取模数时,你都会调用外部过程,这可能会变得很昂贵。 awk内置了这两种功能。

如下面的测试所示,awk速度要快得多:

#!/usr/bin/env bash

seq 1000000 | 
awk '
  BEGIN {
    command = "date +%s"
    prevTime = 0
  }
  $1 % 50000 == 0 {
    command | getline currentTime
    close(command)

    print currentTime - prevTime
    prevTime = currentTime
  }
'

输出:

1335629268
0   
0   
0   
0   
0   
0   
0   
0   
0   
0   
0   
0   
0   
0   
1   
0   
0   
0   
0

请注意,第一个数字相当于date +%s。就像你的测试用例一样,我让第一场比赛成为。

注意

*是的,作者正在谈论Korn Shell,而不是OP标记的bash,但bash和ksh在很多方面都非常相似。 ksh实际上是bash的超集。所以我认为read命令与shell之间没有太大的不同。

答案 1 :(得分:3)

使用你的代码,我看到了相同的增加时间模式(从一开始!)。如果您想要更快的处理,则应使用shell内部功能重写。这是我的bash版本:

tabChar="   "  # put a real tab char here, of course
seq 1000000 > seq.dat
while read s;
do
    if (( ! ( s % 50000 ) )) ;then
        echo $s "${tabChar}" $( expr `date +%s` - $A) 
        A=$(date +%s);
    fi
done < seq.dat

修改 固定的bug,输出表明每一行都在处理,现在只有每50000行获得定时处理。 Doah!

  if ((  s % 50000 )) ;then

已修复

  if (( ! ( s % 50000 ) )) ;then

现在输出echo ${.sh.version} =版本JM 93t + 2010-05-24

50000
100000   1
150000   0
200000   1
250000   0
300000   1
350000   0
400000   1
450000   0
500000   1
550000   0
600000   1
650000   0
700000   1
750000   0

输出bash

50000    480
100000   3
150000   2
200000   3
250000   3
300000   2
350000   3
400000   3
450000   2
500000   2
550000   3
600000   2
650000   2
700000   3
750000   3
800000   2
850000   2
900000   3
950000   2
800000   1
850000   0
900000   1
950000   0
1e+06    1

至于为什么你的原始测试案例需要这么长时间......不确定。我很惊讶地看到每个测试时间和时间的增加。如果你真的需要理解这一点,你可能需要花时间来测试更多的测试内容。也许您会看到正在运行trussstrace的内容(取决于您的基本操作系统)。

我希望这会有所帮助。