0

次のコマンドを呼び出すと、ディスクもCPUもメモリもあまり消費されていないにもかかわらず、実行が遅いことがわかりました(top / iotopで確認)

find . -type f -size +0 -exec ./work.sh {} \;

多くのファイル (>50k) があるため、この特定の検索構造を選択しました。

内部 work.sh は基本的に次のようになります。

prefix=\"$filename\"";"\"$timestamp\"";"\"
SED_ARG="-e 's/^/"$prefix"/'"
zcat $1 | sed = | sed 'N;s/\n/";/' | grep -vE '"timepassed";' | eval sed "$SED_ARG" >> $logfilename

パフォーマンスをプロファイリングまたは改善する方法は何ですか? exec が各ファイルに戻るのを待っているのを見つけたのかもしれませんが、次のファイルの次の exec を生成することができました。

4

2 に答える 2

2

ジョブをチャンクに分割し、シェル ジョブ コントロールを使用して実行します。または、これが日常的なものになる場合は、GNU parallel をインストールしてください。ジョブ制御の例:

cnt=1
find . -type f -size +0 |
while read fname 
do
   zcat $fname | sed = | sed 'N;s/\n/";/' | grep -vE '"timepassed";' | 
             eval sed "$SED_ARG" >> $logfilename &
   [ $(( $cnt % 10  )) -eq 0 ] && wait
   cnt=$(( $cnt + 1 ))
done
wait

これにより、一度に 10 個のジョブが実行されます。システムに合わせて 10 を変更します。より大きな数が常に良い選択であるとは限りません。

$(( % )) はモジュロ - 剰余 - 算術です。したがって、cnt が 10 20 30 の場合 ... $(( $cnt % 10 )) はゼロを返します。値がゼロを返すたびに、スクリプトは待機を呼び出します。最後の待機文 (done の下) は、ループが 10 で割り切れない数 (52002 など) で終了する場合に備えてあります。これはすべて bash の一部です。

于 2013-03-29T02:55:58.563 に答える
0

パイプされたコマンドが多すぎるため、実行が遅い理由の1つだと思います。私が正しく理解していれば、パイプされたコマンドのチェーンを次のように大幅にリファクタリングできます。

zcat $1 | awk -v f="$filename" -v t="$timestamp" '$1 !~ "\"timepassed\";" {
             printf("\"%s\";\"%s\";\"%d\";%s\n", f, t, NR, $0)}' >> $logfilename

上記のコード スニペットが同じ機能を果たしていることを確認したら、find コマンドをもう一度試してパフォーマンスを確認できます。

于 2013-03-29T05:51:36.490 に答える