私のスクリプトに問題がありますか?それとも、BashはPythonよりはるかに遅いですか?

私のスクリプトに問題がありますか?それとも、BashはPythonよりはるかに遅いですか?

ループを10億回実行して、BashとPythonの速度をテストしました。

$ cat python.py
#!/bin/python
# python v3.5
i=0;
while i<=1000000000:
    i=i+1;

クンコード:

$ cat bash2.sh
#!/bin/bash
# bash v4.3
i=0
while [[ $i -le 1000000000 ]]
do
let i++
done

このtimeコマンドを使用すると、Pythonコードは完了するのに48秒しかかかりませんが、Bashコードはスクリプトを終了するのに1時間以上かかることを発見しました。

なぜですか? Bashが速くなると期待しています。私のスクリプトに問題がありますか?または、このスクリプトを使用すると、Bashは本当にはるかに遅くなりますか?

ベストアンサー1

シェルループは遅く、bashのループは最も遅いです。 Shellは、ループ内で重い操作を実行するのには適していません。シェルは、一括データに対していくつかの外部最適化プロセスを開始するように設計されています。


とにかく、シェルループがどのように比較されるのか疑問に思っていくつかのベンチマークを実行しました。

#!/bin/bash

export IT=$((10**6))

echo POSIX:
for sh in dash bash ksh zsh; do
    TIMEFORMAT="%RR %UU %SS $sh"
    time $sh -c 'i=0; while [ "$IT" -gt "$i" ]; do i=$((i+1)); done'
done


echo C-LIKE:
for sh in bash ksh zsh; do
    TIMEFORMAT="%RR %UU %SS $sh"
    time $sh -c 'for ((i=0;i<IT;i++)); do :; done'
done

G=$((10**9))
TIMEFORMAT="%RR %UU %SS 1000*C"
echo 'int main(){ int i,sum; for(i=0;i<IT;i++) sum+=i; printf("%d\n", sum); return 0; }' |
   gcc -include stdio.h -O3 -x c -DIT=$G - 
time ./a.out

詳細:

  • CPU: Intel(R) Core(TM) i5 CPU M 430 @ 2.27GHz
  • ksh: sh バージョン (AT&T Research) 93u+ 2012-08-01
  • bash:GNU bash、バージョン4.3.11(1)-リリース(x86_64-pc-linux-gnu)
  • zsh: zsh 5.2 (x86_64-unknown-linux-gnu)
  • ダッシュ:0.5.7-4ubuntu1

)

(短縮)結果(繰り返しあたりの時間)は次のとおりです。

POSIX:
5.8 µs  dash
8.5 µs ksh
14.6 µs zsh
22.6 µs bash

C-LIKE:
2.7 µs ksh
5.8 µs zsh
11.7 µs bash

C:
0.4 ns C

結果から:

少し速いシェルループが必要な場合は[[構文があり、高速シェルループが必要な場合は高度なシェルにあり、Cに似たforループもあります。次に、C言語のforループを使用します。while [同じシェルの-loopより約2倍高速です。

  • ケシ最速のfor (ループはおおよそ2.7マイクロ秒各繰り返し
  • スプリント最速のwhile [ループはおおよそ5.8マイクロ秒各繰り返し

C for ループは 10 進数 3 ~ 4 倍速くなります。 (TorvaldsがCが好きだと聞きました。)

最適化されたC forループwhile [は、bashループ(最も遅いシェルループ)より56500倍速く、for (kshループ(最も速いシェルループ)より6750倍速いです。


繰り返しますが、シェルの一般的なモードは、外部オプティマイザのいくつかのプロセスでロードをオフロードすることであるため、シェルが遅くなることは重要ではありません。

このパターンを使用すると、シェルでPythonスクリプトよりもパフォーマンスの良いスクリプトを簡単に作成できることがよくあります。

考慮すべきもう一つのことは開始時間です。

time python3 -c ' '

私のPCでは30〜40msかかり、シェルは約3msかかります。多くのスクリプトを起動すると、この時間はすばやく合計され、Pythonの起動にかかる追加の27〜37ミリ秒以内に多くのことができます。この間、小さなスクリプトを複数回完了できます。

(NodeJは起動に約100ミリ秒しかかからないので、おそらくこの部門で最悪のスクリプトランタイムになるでしょう。

おすすめ記事