消除子外壳以加快处理速度?

eliminate subshells for faster process?

我读到调用子 shell 的脚本很慢,这可以解释为什么我的脚本很慢。

例如这里,我 运行 一个从数组中获取数字的循环,这 运行 每次都是一个子 shell,是否可以在不使用子 shell 的情况下解决这个问题?

mmode=1
modes[1,2]="9,12,18,19,20,30,43,44,45,46,47,48,49"
until [[ -z $kik ]];do
    ((++mloop))
    kik=$(echo  ${modes[$mmode,2]} | cut -d "," -f $mloop)
    
    filename=$(basename "$f")
    # is all these lines
    
    xcolorall=$((xcolorall+$storednr)
    # also triggering
    
    pros2=$(echo "100/$totpix*$xcolorall" | bc -l) 
    IFS='.' read -r pros5 pros6 <<< "$pros2"
    procenthittotal2=$pros5.${pros6:0:2}
            
    #subshells and if,
    # is it possible to circumvent it?  
    #and more of the same code..
done

更新: pros2 变量正在计算百分比,有多少 % xcolorall 属于 totpixkik 变量从数组 modes 中获取一个数字,通知循环它应该在这个循环中计算什么颜色。 我怀疑这些是主要的 hoggers,有没有没有 subshel​​ls 的方法?

您可以用 bash 内置命令替换问题中显示的所有子 shell 和外部命令。

  • kik=$(echo ${modes[$mmode,2]} | cut -d "," -f $mloop)可以换成
    mapfile -d, -t -s$((mloop-1)) -n1 kik <<< "${modes[$mmode,2]}".
    如果$mmode在这里不变,最好用
    替换整个循环 while IFS=, read -r kik; do ...; done <<< "${modes[$mmode,2]}".
  • filename=$(basename "$f")可以换成
    filename=${f##*/} 运行速度快 100 倍,参见 benchmark
  • pros2=$(echo "100/$totpix*$xcolorall" | bc -l)可以换成
    (( pros2 = 100 * xcolorall / totpix )) 如果您不关心小数点,或者
    precision=2; (( pros = 10**precision * 100 * xcolorall / totpix )); printf -v pros "%0${precision}d" "$pros"; pros="${pros:0: -precision}.${pros: -precision}" 如果你想要小数点后两位。
    当然,您可以省略最后的命令(用于将 12345 转换为 123.45),直到您真正需要十进制数。

但如果速度真的很重要,请用另一种语言编写脚本。我认为 awkperlpython 在这里很合适。