shell 脚本中的字符串填充性能:最佳数量是多少以及适用于什么 shell?

shell 脚本中的字符串填充性能:最佳数量是多少以及适用于什么 shell?

我试图确定字符串填充的最佳性能,如下所示:
str+="A"#one perloop

我为 bash 提供了这个脚本:

#!/bin/bash
bReport=false
nLimit=${1-3000}; #up to 25000

echo "nLimit='$nLimit'"
shopt -s expand_aliases
nStop=100000;fMaxWorkTime=1.0;
alias GetTime='date +"%s.%N"';
nTimeBegin="`GetTime`";
nDelayPart="`GetTime`";
strFinal="";
str="";
fPartWorkSleep="`bc <<< "scale=10;($fMaxWorkTime/$nStop)*$nLimit"`"
echo "fPartWorkSleep='$fPartWorkSleep'"
nCount=0;
while true;do 
    str+="A";
    ((nCount++))&&:;
    if(((nCount%nLimit)==0)) || ((nCount==nStop));then 
        strFinal+="$str";
        str="";
        if $bReport;then
            echo "`bc <<< "$(GetTime)-$nDelayPart"` #${#strFinal} #`bc <<< "$(GetTime)-$nTimeBegin"`";
            nDelayPart="`GetTime`";
        fi
        sleep $fPartWorkSleep # like doing some weigthy thing based on the amount of data processed
    fi;
    if((nCount==nStop));then 
        break;
    fi;
done;
echo "strFinal size ${#strFinal}"
echo "took `bc <<< "$(GetTime)-$nTimeBegin"`"

在 bash 中,最好的性能/大小是str限制在 3000 到 25000 个字符之间(在我的机器上)。每个部分填满后,必须将其清空,并可以执行一些有重量的动作str(并且重量与其大小有关)。

所以我的问题是,什么 shell 具有最好的字符串填充性能?根据我所曝光的内容。我愿意使用bash以外的其他shell,只是为了这种算法,如果事实证明它更快。

PS:我不得不使用 nCount 作为检查字符串大小降低性能的方法。

答案1

for sh  in bash zsh yash dash mksh ksh
do      printf  "\n%s:\t" "$sh"
        time    "$sh" -c '
                        str="some string"
                        set     "" ""
                        while   ${20001+"break"}
                        do      set "$@$@";done
                        IFS=A;  printf %.100000s\\n "$str$*$*$*$*$*"'|
                wc -c
done

bash:   100001
"$sh" -c   0.15s user 0.01s system 94% cpu 0.176 total
wc -c  0.00s user 0.00s system 1% cpu 0.175 total

zsh:    100001
"$sh" -c   0.03s user 0.01s system 97% cpu 0.034 total
wc -c  0.00s user 0.00s system 9% cpu 0.034 total

yash:   100001
"$sh" -c   0.06s user 0.01s system 94% cpu 0.067 total
wc -c  0.00s user 0.00s system 5% cpu 0.067 total

dash:   100001
"$sh" -c   0.02s user 0.01s system 92% cpu 0.029 total
wc -c  0.00s user 0.00s system 11% cpu 0.028 total

ksh:    100001
"$sh" -c   0.02s user 0.00s system 96% cpu 0.021 total
wc -c  0.00s user 0.00s system 16% cpu 0.021 total

$sh因此,这对循环中设置的各种 shellfor生成 100,000 个字符的字符串的速度进行了测试。这 100,000 个字符中的前 11 个是some stringas 首先设置为 的值$str,但尾部填充为 999,989A字符。

贝壳得到Achars,$*其中替换特殊 shell 参数值中的第一个字符,$IFS作为 shell 参数数组中每个位置参数之间的串联分隔符。因为所有参数均为""空,所以中唯一的字符$* 分隔符。

对于循环的每次迭代,参数以指数速率累积while- 仅break$20001参数最终出现时才发生${set+}。在那之前,while循环基本上会执行以下操作:

### first iteration
while $unset_param; do set "" """" ""; done
### second iteration
while $unset_param; do set "" "" """" "" ""; done
### third iteration
while $unset_param; do set "" "" "" "" """" "" "" "" ""; done

...等等。

while循环完成后$IFS设置为A并且特殊的 shell 参数$*在 的尾部连接五次$str。在将printf结果写入 stdout 之前将%s其修剪为最大字节数。.100000

人们可能会使用相同的策略,例如:

str='some string'
set "" ""
while ${51+"break"}; do set "$@$@"; done
shift "$((${#}-(51-${#str}))"

...这导致参数总数为 40 - 因此有 39 个分隔符...

IFS=.; printf %s\\n "$str$*"

some string.......................................

您还可以重复使用已经为不同的设置设置的相同$IFS参数充满:

for IFS in a b c; do printf %s\\n "$str$*"; done

some stringaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
some stringbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
some stringccccccccccccccccccccccccccccccccccccccc

您还可以使用格式字符串填充空参数,printf而不是使用$IFS

printf "%s m%sy%1ss%st%sr%si%sn%sg" "$str$@"

some string my string my string my string my string my string

相关内容