4

序文:

whileシェルで作業するときは、ループよりもループを実行する方が望ましいこと、およびファイルをコマンド置換でループをfor使用するべきではないことを常に教えられてきました。私の理解では、これには次のような多くの理由があります。forcat

  • forループでは、処理するすべてのデータを一度にメモリにロードする必要があります
  • forループは、デフォルトでは改行ではなく空白で単語分割を行うため、ファイル内のすべてをメモリに保持する必要があることに加えて、メモリを占有する単語分割も多くなります
  • forinループは、ステートメント内のすべての読み込みが完了するまで「do の右側」で処理を開始しません。つまり、結果を待っている時間の一部は、「プリロード」している間は実際には何も起きていません。 .

ただし、いくつかの簡単なテストを行ったところ、for(予想どおり) ループではメモリ消費量が多いように見えますが、ループの実際のパフォーマンスwhileは低いことがわかりました。それは大きな違いではなく、これが最新のマシンで問題になり始める可能性が高い規模では、おそらく awk または python に切り替えることになるでしょうが、なぜこれが起こっているのかまだ興味があります.

テスト設定:

ファイルの行を /dev/null にエコーするだけの簡単な一連のテストを行いました。私の入力は、それぞれ 100K と 1Mil の IP アドレスを含む 2 つのフラット ファイルです。以下の出力は 1 つのテストですが、これを数回実行すると毎回同様の結果が得られました。2013 MBA (i7、8g Mem) でこのテストを実行していました。

試験結果

Ds-MacBook-Air:~ d$ time for i in $(cat /tmp/ips.100k);do echo $i > /dev/null;done

real    0m1.629s
user    0m1.154s
sys 0m0.480s
Ds-MacBook-Air:~ d$ time for i in $(cat /tmp/ips.mill);do echo $i > /dev/null;done

real    0m17.567s
user    0m12.414s
sys 0m5.131s
Ds-MacBook-Air:~ d$ time while read i;do echo $i > /dev/null;done < /tmp/ips.100k

real    0m2.148s
user    0m1.493s
sys 0m0.655s
Ds-MacBook-Air:~ d$ time while read i;do echo $i > /dev/null;done < /tmp/ips.mill

real    0m21.536s
user    0m14.915s
sys 0m6.617s

Ds-MacBook-Air:~ d$ tail -5 /tmp/ips.100k /tmp/ips.mill
==> /tmp/ips.100k <==
1.1.134.155
1.1.134.156
1.1.134.157
1.1.134.158
1.1.134.159

==> /tmp/ips.mill <==
1.15.66.59
1.15.66.60
1.15.66.61
1.15.66.62
1.15.66.63

Ds-MacBook-Air:~ d$ wc -l /tmp/ips.100k /tmp/ips.mill
  100000 /tmp/ips.100k
 1000000 /tmp/ips.mill
 1100000 total

forループとループに関して私が主張したことについて直接の引用はありませんが、while具体的には ~~TLDP~~ Wooldridge のドキュメント、または別の Bash プログラミング ガイド (簡単なグーグル検索では私がこの数年前にほとんど読んだ正確な場所.)

4

1 に答える 1

5

ここでの違いは、$(cat testfile)テスト ファイル全体を一度にメモリに読み込んで文字列分割するwhile read場合と、一度に 1 行ずつ読み込む場合です。

当然のことながら、大量の読み取りの数が少ないほど効率的です。

アプローチによって導入されたバグもあり$(cat testfile)ます。これは、ファイルの内容を文字列分割 (ご存知のとおり) およびグロブ展開 (そうでない可能性があります) します。つまり、 がある場合は*置き換えることができます現在のディレクトリ内のファイルのリストによって。

于 2013-09-17T02:47:28.343 に答える