Shellscript で指定回数ループするコードのベンチマーク
Shellscript で 指定回数ループする場合を調べていたら、
while でインクリメントしていくか、for in seq の2 パターンが見つかった。
どちらが高速なのか疑問に思ったのでベンチマークを取った。
while
code
#!/bin/sh i=0 while [ $i -ne 10000 ]; do i=`expr $i + 1` echo $i done
result
$ time ./while.sh real 0m20.557s user 0m4.466s sys 0m10.371s
for
code
#!/bin/sh for i in `seq 1 10000`; do echo $i; done
result
$ time ./for.sh real 0m0.188s user 0m0.132s sys 0m0.041s
考察
while が圧倒的に遅いことがわかった。
この結果から、while で行っている変数代入、expr、while 自体、のいずれかが遅いと考えられる。
そこで、この3つのどこに原因があるのか調査した。
while 自体が遅い?
これはほとんどないと思われるが一応ベンチをとる。
code
seq の結果をパイプで渡して、read すれば for in seq と大体同等の処理になると思われる(多分)。
seq 1 10000 | while read i; do echo $i done
result
$ time ./seq_while.sh real 0m0.239s user 0m0.184s sys 0m0.061s
read の分で for より少し遅くなっていると思われるが、誤差の範囲内である。
変数代入
code
seq_while.sh に 代入を加えただけ。
seq 1 10000 | while read i; do hoge=$i echo $i done
result
$ time ./assign.sh real 0m0.326s user 0m0.250s sys 0m0.092s
seq_while.sh より少し遅くなったくらいで、これも原因ではなさそうだ。
expr
消去法で、これが原因だとわかる。
結論
expr は遅いので、指定回数ループを回すときには使わないほうが良い。
また、expr 自体コストが高いようなので四則演算を頻繁に行う場合は、perl などに行わせたほうが良いのだと思う。
dstat で expr のループを見ていたがそこそこ CPU を喰っていたので、CPU リソースの観点からも使わないほうが良いと思われる。
おまけ
以下のような perl script もベンチをとってみた。
code
for my $i (1..10000) { print $i + 1, "\n"; }
result
$ time perl ./loop.pl real 0m0.044s user 0m0.017s sys 0m0.026s
四則演算しても、shellscript より perl のほうが速い。
2014/04/08 追記
id:hirata_yasuyuki さんにコメントいただいた、$(()) (以下、算術式展開)のベンチマークもとってみました。
id:hirata_yasuyuki さん、ありがとうございます。
以前の環境が思い出せないので、expr と for seq を再度実行して、結果の比較を行った。
expr
code
while.sh と同じ
result
real 0m17.375s user 0m4.588s sys 0m8.534s
for seq
code
for.sh と同じ
result
real 0m0.207s user 0m0.154s sys 0m0.028s
算術式展開
code
#!/bin/sh i=0 while [ $i -ne 10000 ]; do i=$(($i+1)) echo $i done
result
real 0m0.291s user 0m0.254s sys 0m0.035s
結論
ご指摘いただいた通り、算術式展開を使ったほうが圧倒的に速い。
また、for seq とも大差ない結果だった。
ただ、私の手元にある以下の書籍には、
BSDの一部の sh で一部使用できない演算子があったり、Solaris の sh だとそもそも使えない?らしく、移植性を重視したい場合は、expr を使ったほうが良いと記されていました(共に未検証)。
[改訂新版] シェルスクリプト基本リファレンス ??#!/bin/shで、ここまでできる (WEB+DB PRESS plus)
- 作者: 山森丈範
- 出版社/メーカー: 技術評論社
- 発売日: 2011/04/27
- メディア: 単行本(ソフトカバー)
- 購入: 9人 クリック: 119回
- この商品を含むブログ (11件) を見る
しかし、Linux 上で使うだけであれば、算術式展開で十分だと思われる。