dashまたは他のシェルがbashよりも「高速ですか?」

dashまたは他のシェルがbashよりも「高速ですか?」

私はいつもbashの代わりにダッシュを使用する唯一の利点は、ダッシュが小さいので、多くのダッシュインスタンスが起動時により早く開始されることだと思いました。

しかし、調査をしてみると、一部の人々はより速く実行されることを望んですべてのスクリプトをダッシュ​​に移行するという事実を発見しました。記事でもこの内容を発見しました。ダッシュUbuntu Wikipediaから:

基本シェルを切り替える主な理由は効率。 bashはインタラクティブな使用に適した優れた機能を備えたシェルであり、実際にはまだデフォルトのログインシェルです。しかし、規模はかなり大きくてスロースタートそして運営するダッシュと比較。

最近私は私のシステムの多くの仕事にbashスクリプトをたくさん使っています。私の問題は、年中無休の24時間連続で実行する特定のスクリプトがあり、このスクリプトが一緒にマイコンピュータをダウンさせる約200の添え字を生成することです。最大10℃以上加熱されます。通常の使用時より

bashismがたくさん含まれているかなり大きなスクリプトなので、これをPOSIXや他のシェルに移植するのにかなりの時間がかかります(POSIXは個人的な用途にとってそれほど重要ではありません)。しかし、一部を減らすことができれば価値があるでしょう。 CPU使用量です。たとえば、sed単純なbashismを呼び出すために外部バイナリを呼び出すなど、考慮する必要がある他のものがあることを知っています。${foo/bar}grep=~

長い話を短くbashの起動速度は本当に遅いです。そして運営するダッシュと比べると?より強力なUnixシェルはありますか?効率的なバッシュより?

ベストアンサー1

シェル順序:

おそらくシェルのパフォーマンスをベンチマークする便利な方法は、非常に小さくて簡単な評価を多数繰り返すことです。私は単にループを繰り返さないことが重要だと思います。入力する、シェルが読む必要があるからです<&0

私はこれがテストを補完すると思った@cuonglm 投稿しましたこれは、呼び出し時にシェルプロセスがどれだけ早くロードされるかを示すのではなく、呼び出し後の単一のシェルプロセスのパフォーマンスを示すためです。このように、我々は私たちの間のコインの両面を覆います。

簡単に実演できる機能は次のとおりです。

sh_bench() (                                               #don't 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実際には前の行から呼び出されたためです);呼び出された時点から終了するまで、他のプロセスは呼び出されません。少なくともそれが本当であることを願っています。

数字の前に...

移植性についていくつかのメモを取る必要があります。

  • posh嫌い$((n=n+1))で頑固$((n=$n+1))

  • mkshprintfほとんどの場合、組み込み機能はありません。初期テストでは、遅延が多く発生し、/usr/bin/printf実行されるたびに呼び出されました。したがって、上記のような状況が発生しますecho -n

  • おそらく私の記憶ではもっと多いかもしれません...

とにかく数字を見ると次のようになります。

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

    

誰=多分?

それでも、これはかなりランダムなテストですが、入力読み出し、算術評価、および変数拡張をテストします。包括的ではありませんが、おそらくそれに近いです。

編集者: Teresa e Junior:@mikeservと私は他の多くのテストを行いました(参照私たちのチャット詳細)結果を次のように要約できることを確認しました。

  • 速度が必要な場合は必ず選択してくださいスプリント、これは他のシェルよりはるかに高速です。強く打つ
  • しかし、忙しい箱殻はおそらく良いと思います。スプリント、一般的に使用されるGNUユーティリティほど多くの機能はありませんが、それほど多くの作業を行うことができる、、などの独自のgrepユーザー空間ユーティリティが多いため、一部のテストではより速い場合があります。 。sedsort
  • 速度があなたのすべてではない場合ケシ(またはクッシュ 93)は、速度と機能性の間の最良の妥協点と見なすことができます。小さいものに比べて速度が速いムケシ、これよりも優れています。強く打つで、次のようないくつかのユニークな機能もあります。浮動小数点演算
  • しかし、強く打つ単純さ、安定性、機能性としてよく知られていますが、ほとんどのテストでは、すべてのシェルの中で最も遅く、速度も非常に多様でした。

おすすめ記事