【问题标题】:Bash pattern matching loop super slow [duplicate]Bash模式匹配循环超级慢[重复]
【发布时间】:2018-10-26 03:17:35
【问题描述】:

当我使用 awk 执行此操作时,它相对较快,即使它是 Row By Agonizing Row (RBAR)。我试图在 Bash 中创建一个更快更优雅的 bug 抵抗解决方案,它只需要通过文件进行更少的传递。使用此代码通过 bash 完成前 1,000 行可能需要 10 秒。我可以在大约同一时间用 awk 完成 25 次遍历所有百万行文件! bash 怎么慢了几个数量级?

  while read line
    do
    FIELD_1=`echo "$line" | cut -f1`
    FIELD_2=`echo "$line" | cut -f2`

    if [ "$MAIN_REF" == "$FIELD_1" ]; then
      #echo "$line"
      if [ "$FIELD_2" == "$REF_1" ]; then
         ((REF_1_COUNT++))
      fi

      ((LINE_COUNT++))

      if [ "$LINE_COUNT" == "1000" ]; then
        echo $LINE_COUNT;
      fi
    fi
done < temp/refmatch

【问题讨论】:

  • 因为 read 很慢 - stackoverflow.com/questions/13762625/… 为什么不用 Python 写这个?这里没有什么需要特定于 bash。
  • 您的代码创建了太多进程,这会使它变得更慢。 awk 或 python 是你最好的选择。

标签: bash io


【解决方案1】:

Bash 很慢。就是那样子;它旨在监督特定工具的执行,并且从未针对性能进行过优化。

同样,您可以通过避免明显的低效率来降低速度。例如,read 会将其输入拆分为单独的单词,这样写起来会更快更清晰:

while read -r field1 field2 rest; do
  # Do something with field1 and field2

而不是

while read line
    do
    FIELD_1=`echo "$line" | cut -f1`
    FIELD_2=`echo "$line" | cut -f2`

您的版本设置了两条管道,并为每一行输入(至少)创建了四个孩子,而使用 read 的设计方式不需要任何外部进程。

如果您使用cut,因为您的行是制表符分隔的,而不仅仅是空格分隔,您可以通过在本地设置IFS 来实现与read 相同的效果:

while IFS=$'\t' read -r field1 field2 rest; do
  # Do something with field1 and field2

即便如此,不要指望它会很快。它只会变得不那么缓慢。你最好修复你的 awk 脚本,这样它就不需要多次传递。 (如果你可以用 bash 做到这一点,也可以用 awk 完成,而且可能用更少的代码。)

注意:我设置了三个变量而不是两个,因为read 将行的其余部分放入最后一个变量中。如果只有两个字段,则无害;将变量设置为空字符串是 bash 可以相当迅速地完成的事情。

【讨论】:

    【解决方案2】:

    正如@codeforester 指出的那样,原始的 bash 脚本产生了如此多的子进程。
    这是为了最大限度地减少开销的修改版本:

    #!/bin/bash
    
    while IFS=$'\t' read -r FIELD_1 FIELD_2 others; do
    
      if [[ "$MAIN_REF" == "$FIELD_1" ]]; then
        #echo "$line"
        if [[ "$FIELD_2" == "$REF_1" ]]; then
          let REF_1_COUNT++
        fi
    
        let LINE_COUNT++
          echo "$LINE_COUNT"
    
        if [[ "$LINE_COUNT" == "1000" ]]; then
          echo "$LINE_COUNT"
        fi
      fi
    done < temp/refmatch
    

    它的运行速度比原来快了 20 倍以上,但恐怕这可能是 bash 脚本的限制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-20
      • 2014-05-15
      • 1970-01-01
      • 2011-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多