シェル配列:
おそらく、シェルのパフォーマンスをベンチマークでマークする便利な方法は、非常に小さく単純な評価を繰り返し行うことです。シェルが読み取る必要があるため、ループするだけでなく、入力をループすることが重要だと思います<&0
。
これは、シェルプロセスが呼び出されたときにどれだけ速くロードされるかを示すのに対して、@ cuonglmがすでに投稿されたテストを補完するものだと思いました。このようにして、私たちの間で、コインの両側を覆います。
デモを容易にする機能は次のとおりです。
sh_bench() ( #dont copy+paste comments
o=-c sh=$(command -v "$1") ; shift #get shell $PATH; toss $1
[ -z "${sh##*busybox}" ] && o='ash -c' #cause its weird
set -- "$sh" $o "'$(cat <&3)'" -- "$@" #$@ = invoke $shell
time env - "$sh" $o "while echo; do echo; done|$*" #time (env - sh|sh) AC/DC
) 3<<-\SCRIPT
#Everything from here down is run by the different shells
i="${2:-1}" l="${1:-100}" d="${3:-
}"; set -- "\$((n=\$n\${n:++\$i}))\$d" #prep loop; prep eval
set -- $1$1$1$1$1$1$1$1$1$1 #yup
while read m #iterate on input
do [ $(($i*50+${n:=-$i})) -gt "$(($l-$i))" ] || #eval ok?
eval echo -n \""$1$1$1$1$1"\" #yay!
[ $((n=$i+$n)) -gt "$(($l-$i))" ] && #end game?
echo "$n" && exit #and EXIT
echo -n "$n$d" #damn - maybe next time
done #done
#END
SCRIPT #end heredoc
改行の読み取りごとに1回変数をインクリメントするか、可能であれば少し最適化して、改行の読み取りごとに50インクリメントします。変数がインクリメントされるたびに、変数に出力されstdout
ます。それは一種のseq
十字架のようにふるまいnl
ます。
そして、それが何をするのかを非常に明確にするために- 上記の関数のset -x;
直前に挿入した後の出力の一部を以下time
に示します。
time env - /usr/bin/busybox ash -c '
while echo; do echo; done |
/usr/bin/busybox ash -c '"'$(
cat <&3
)'"' -- 20 5 busybox'
したがって、各シェルは最初に次のように呼び出されます。
env - $shell -c "while echo; do echo; done |..."
...読み込み時にループオーバーする必要がある入力を生成します3<<\SCRIPT
- cat
とにかくそうする場合。そしてその反対側では、次の|pipe
ように再び自分自身を呼び出します:
"...| $shell -c '$(cat <<\SCRIPT)' -- $args"
だから、わきの最初の呼び出しからenv
(ので、cat
実際には前の行に呼ばれています)。呼び出されてから終了するまで、他のプロセスは呼び出されません。少なくとも、それが本当であることを願っています。
数字の前に...
移植性についていくつか注意する必要があります。
とにかく、数字に:
for sh in dash busybox posh ksh mksh zsh bash
do sh_bench $sh 20 5 $sh 2>/dev/null
sh_bench $sh 500000 | wc -l
echo ; done
それはすべて一度にそれらを取得します...
0dash5dash10dash15dash20
real 0m0.909s
user 0m0.897s
sys 0m0.070s
500001
0busybox5busybox10busybox15busybox20
real 0m1.809s
user 0m1.787s
sys 0m0.107s
500001
0posh5posh10posh15posh20
real 0m2.010s
user 0m2.060s
sys 0m0.067s
500001
0ksh5ksh10ksh15ksh20
real 0m2.019s
user 0m1.970s
sys 0m0.047s
500001
0mksh5mksh10mksh15mksh20
real 0m2.287s
user 0m2.340s
sys 0m0.073s
500001
0zsh5zsh10zsh15zsh20
real 0m2.648s
user 0m2.223s
sys 0m0.423s
500001
0bash5bash10bash15bash20
real 0m3.966s
user 0m3.907s
sys 0m0.213s
500001
任意=大丈夫ですか?
それでも、これはかなりarbitrary意的なテストですが、入力値の読み取り、算術評価、変数展開をテストします。包括的ではないかもしれませんが、おそらくそこに近いでしょう。
編集by Teresa e Junior:@mikeservと私は他にも多くのテストを行っています(詳細についてはチャットをご覧ください)。結果は次のように要約できることがわかりました。
- 速度が必要な場合は、必ずdashを使用してください。他のシェルよりもはるかに高速で、bashよりも約4倍高速です。
- 一方でbusyboxののシェルがよりはるかに遅くなることがダッシュそれは、独自のユーザランドユーティリティの多くを持っているので、いくつかのテストでは、速くなる可能性のような
grep
、sed
、sort
、など、一般的に使用されるGNUほど多くの機能を持ちませんユーティリティが、仕事をすることができます。
- 速度が気になるすべてではない場合は、ksh(またはksh93)が速度と機能の最適な比較と見なすことができます。速度はbashよりもはるかに高速な、より小さなmkshと比較し、浮動小数点演算などのいくつかのユニークな機能も備えています。
- が、bashは、そのシンプルさ、安定性、および機能のために有名である、それは、大きなマージンによって、我々のテストの大部分において、すべてのシェルの最も遅いでした。