web-dev-qa-db-ja.com

ループと拡張のパフォーマンス

以下の比較について専門家の提案が必要です:

ループを使用したコードセグメント:

for file in `cat large_file_list`
do
    gzip -d $file
done

単純な拡張を使用したコードセグメント:

gzip -d `cat large_file_list`

どちらが速くなりますか?大きなデータセットを操作する必要があります。

9
Leon

合併症

以下は時々しか機能しません:

gzip -d `cat large_file_list`

3つの問題があります(bashおよび他のほとんどのBourneのようなシェルで):

  1. ファイル名にスペースタブまたは改行文字が含まれている場合は失敗します($IFSが変更されていない場合)。これは、シェルの単語分割が原因です。

  2. また、ファイル名にglob-active文字が含まれていると、失敗する可能性があります。これは、シェルがパス名展開をファイルリストに適用するためです。

  3. また、ファイル名が-で始まる場合(最初のファイルにのみ適用されるPOSIXLY_CORRECT=1の場合)、またはファイル名が-の場合も失敗します。

  4. ファイル名が多すぎて1つのコマンドラインに収まらない場合も失敗します。

以下のコードには、上記のコードと同じ問題があります(4番目を除く)。

for file in `cat large_file_list`
do
    gzip -d $file
done

信頼できるソリューション

large_file_listのファイル名が1行に1つだけあり、-というファイルがその中にない場合、GNUシステム上にいる場合は、次のように使用します。

xargs -rd'\n' gzip -d -- <large_file_list

-d'\n'は、入力の各行を個別のファイル名として扱うようにxargsに指示します。

-rは、入力ファイルが空の場合、コマンドを実行しないようにxargsに指示します。

--は、次の引数が-で始まっていても、オプションとして扱われないことをgzipに伝えます。ただし、-だけでは、-というファイルではなく、-として扱われます。

xargsは、各コマンドラインに多くのファイル名を付けますが、コマンドラインの制限を超えるほどではありません。これにより、gzipプロセスを開始する必要がある回数が減るため、これが高速になります。また、安全です。ファイル名もWord分割およびパス名展開から保護されます。

19
John1024

それが大事だとは思いません。

リストファイルにリストされているファイルの数がわからず、ファイル名の名前にスペースが含まれているかどうかが(一般的に)わからないため、ループを使用します。非常に長い引数のリストを生成するコマンド置換を実行すると、生成されたリストの長さが長すぎる場合に、「引数リストが長すぎます」というエラーが発生する可能性があります。

私のループは次のようになります

while IFS= read -r name; do
    gunzip "$name"
done <file.list

これにより、gunzipコマンドの後にデータを処理するためのコマンドを追加できます。実際、データが実際に何であり、それを使って何をする必要があるかに応じて、ファイルにまったく保存せずに処理することもできます。

while IFS= read -r name; do
    zcat "$name" | process_data
done <file.list

(どこ process_dataは、非圧縮データを標準入力から読み取るパイプラインです)

データの処理にデータの圧縮解除よりも時間がかかる場合、ループがより効率的であるかどうかの問題は関係ありません。

理想的には、ファイル名のリストを使用せず、代わりに次のようにファイル名グロビングパターンを使用します

for name in ./*.gz; do
    # processing of "$name" here
done

どこ ./*.gzは、関連ファイルに一致するパターンです。この方法では、ファイルの数やファイル名に使用されている文字に依存しません(ファイルには改行やその他の空白文字が含まれている場合や、ダッシュなどで始まる場合があります)。

関連:

12
Kusalananda

これらの2つのうち、gzipを1回呼び出すだけでよいので、gzipの1回の呼び出しにすべてのファイルが渡される方が高速になる可能性があります。 (つまり、コマンドがまったく機能する場合は、警告の他の回答を参照してください。)

しかし、私は ゴールデンの最適化ルール を思い出したいと思います:時期尚早にそれをしないでください。

  1. 問題であることを知る前に、そのようなことを最適化しないでください。

    プログラムのこの部分には長い時間がかかりますか?さて、大きなファイルを解凍すると、とにかくそれを行わなければならないので、答えるのはそれほど簡単ではないかもしれません。

  2. 測定します。確かに、これが確実な最良の方法です。

    結果は自分の目で(または独自のストップウォッチで)表示され、インターネットでのランダムな回答ではできない状況に適用されます。両方のバリアントをスクリプトに入れ、time script1.shおよびtime script2.shを実行します。 (オーバーヘッドの絶対量を測定するには、空の圧縮ファイルのリストを使用してそれを行います。)

5
ilkkachu

あなたのディスクはどれくらい速いですか?

これはすべてのCPUを使用するはずです。

parallel -X gzip -d :::: large_file_list

したがって、あなたの限界はおそらくあなたのディスクの速度になるでしょう。

-jで調整してみてください:

parallel -j50% -X gzip -d :::: large_file_list

これにより、前のコマンドと同じようにジョブの半分が並行して実行され、ディスクにかかる負荷が少なくなるため、ディスクによってはこれが高速になる場合があります。

0
Ole Tange