シェルスクリプトの文字列パディングパフォーマンス:最適な量はどのくらいで、どのシェルに適していますか?

シェルスクリプトの文字列パディングパフォーマンス:最適な量はどのくらいで、どのシェルに適していますか?

私は次のように文字列パディングの最高のパフォーマンスを決定しようとしています:
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では、最高のパフォーマンス/サイズはstr3000〜25000文字(マイコンピュータでは)に制限されています。各セクションがいっぱいになると空にする必要がありますstr

私の質問は、どのシェルが文字列パディングのパフォーマンスが最善ですか?私が公開した内容に基づいています。私はこのアルゴリズムがより高速であることが証明されている場合は、bash以外のシェルを使用することになります。

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したがって、これはforループに設定されたさまざまなシェルが100,000文字列を生成できる速度のテストでした。 100,000文字のうち最初の11文字は次のとおりです。some stringasは最初に値に設定されていましたが、$str尾部分は999,989として追加されました。A性格。

殻は得るAcharsは、シェルパラメータ配列の各位置パラメータ間の接続区切り文字で、特殊シェル$*パラメータ値の最初の文字を置き換えます。$IFSすべてのパラメータが""空なので$* はい分離記号。

ループが繰り返されるたびに、パラメータは指数関数的な割合で累積されます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そして、特別なシェルパラメータは$*最後に5回接続されます$str。結果をprintfstdoutに書き込む前に%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

おすすめ記事