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


9

以下の比較に関する専門家の提案が必要です:

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

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

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

gzip -d `cat large_file_list`

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


1
正しい答えはgzip、システムでの起動にかかる時間、ファイルリスト内のファイル数、およびそれらのファイルのサイズによって異なります。
クサラナンダ

ファイルリストには、約1000〜10000のファイルがあります。サイズは、数キロバイトから500 MBまでさまざまです。私のシステムでgzipを開始するのにどれくらい時間がかかるかわかりません。何かチェック?
レオン

1
OK、それはファイル名の長さに依存するかもしれません。ファイル名が長い場合、システムによっては、ループなしで実行しようとすると、「引数リストが長すぎます」というエラーが生成されることがあります。これは、コマンド置換により、シェルが実行するコマンドラインが長すぎるためです。リスト内のファイル数に依存したくない場合は、ループを使用してください。これらのファイルを圧縮解除するために実行する他の処理と比較して、これらのファイルの解凍にかなりの時間を費やしていますか?
クサラナンダ

Leonが私のテスト結果を見てみましょう。「huge-arglist」は私の設定の「loop」よりも20倍高速です。

プロセスの開始とコマンドラインの長さの中間の幸せな場合は、次のようなものを使用xargs gzip -d < large_file_listしますが、ファイル名のスペースに注意してください。おそらくtr \\n \\0 large_file_list | xargs -0 gzip -d
w00t

回答:


19

合併症

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

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つのファイル名を持つ、と呼ばれるファイルは、-それらの間ではなく、あなたがGNUシステムにしている場合、使用します。

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

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

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

--告げるgzip彼らが起動しても、次の引数がオプションとして扱われていないこと--それだけでは-、呼び出されたファイルの代わりとして扱われ-ます。

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


詳しい返信ありがとうございます。言及された3つの問題を理解しました。ファイル名は単純で、リストは最大20000まで保持できるため、これらの課題に直面することはありません。私の質問は、基本的にこれら2つのセグメントのパフォーマンスに関するものです。ありがとう。
レオン

1
@Leon forループは最も断然遅くなります。他の2つの方法は、速度が非常に近くなります。
John1024

7
また、潜在的な問題を無視しないでください。StackExchangeに関する多くの質問は、単語の分割パス名の拡張が、それを予期していない人々に起こったためです。
John1024

5
また、xargs少なくともGNUバージョンには--arg-fileオプション(省略形-a)があります。したがって、xargs -a large_file_list -rd'\n' gzip -d 代わりに行うことができます。事実上、<シェルオペレーターでありxargs、stdin(シェルがファイルに「リンク」)から読み取り-aを行いxargs、問題のファイルを明示的に開くことを除いて、違いはありません
Sergiy Kolodyazhnyy

2
terdonは、のparallel複数のコピーを実行するために使用することについての別のコメントで言及しましたgzipが、xargs(少なくともGNUのものは)-Pそのためのスイッチも持っています。違いをもたらす可能性のあるマルチコアマシン。しかし、いずれにしても、解凍が完全にI / Oに依存している可能性もあります。
ilkkachu

12

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

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

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

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関連するファイルと一致するいくつかのパターンがあります。このようにして、ファイルの数やファイル名に使用されている文字に依存しません(改行やその他の空白文字が含まれていたり、ダッシュで始まっているなど)。

関連:


5

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

しかし、私は思い出させるしたい最適化の黄金ルールDoが早まっそれをしません。

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

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

  2. 測定。確かに、それは確かに最善の方法です。

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


0

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

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

parallel -X gzip -d :::: large_file_list

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

あなたはで調整してみることができます-j

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.