5

bashプログラミングにファイルへの書き込みバッファはありますか? もしあれば、そのサイズを変更することは可能ですか。

ここに問題があります

ファイルを1行ずつ読み取り、読み取ったデータを操作して、結果を別のファイルに書き込むbashスクリプトがあります。このようなもの

while read line 
  some grep, but and sed
  echo and append to another file

入力データは非常に巨大です (約 20 GB のテキスト ファイル)。進行が遅いため、bash のデフォルトの動作が読み取り行ごとに結果を出力ファイルに書き込むことである場合、進行が遅くなるという疑問が生じます。

知りたいのですが、いくつかの出力をバッファリングしてから、そのチャンクをファイルに書き込むメカニズムはありますか? この問題についてインターネットで検索しましたが、有益な情報は見つかりませんでした...

OS 関連の質問ですか、それとも bash ですか? OSはcentosリリース6です。

スクリプトは

#!/bin/bash
BENCH=$1
grep "CPU  0" $BENCH > `pwd`/$BENCH.cpu0
grep -oP '(?<=<[vp]:0x)[0-9a-z]+' `pwd`/$BENCH.cpu0 | sed 'N;s/\n/ /' |  tr '[:lower:]' '[:upper:]' > `pwd`/$BENCH.cpu0.data.VP
echo "grep done"
while read line ; do
   w1=`echo $line | cut -d ' ' -f1`
   w11=`echo "ibase=16; $w1" | bc`
   w2=`echo $line | cut -d ' ' -f2`
   w22=`echo "ibase=16; $w2" | bc`
   echo $w11 $w22 >> `pwd`/$BENCH.cpu0.data.VP.decimal
done <"`pwd`/$BENCH.cpu0.data.VP"
echo "convertion done"
4

2 に答える 2

5

ループ内の各エコーと追加は、パフォーマンスに悪影響を及ぼす可能性があるファイルを開いたり閉じたりしています。

おそらくより良いアプローチ(そしてプロファイルする必要があります)は単純です:

grep 'foo' | sed 's/bar/baz' | [any other stream operations] <$input_file >$output_file 

既存の構造を維持する必要がある場合は、名前付きパイプを作成する別の方法があります。

mkfifo buffer

次に、パイプに書き込むプロセスと、パイプから読み取るプロセスの 2 つのプロセスを作成します。

#proc1
while read line <$input_file; do
    grep foo | sed 's/bar/baz' >buffer
done


#proc2
while read line <buffer; do
    echo line >>$output_file
done

実際には、ボトルネックは完全にファイル IO であると予想されますが、これにより、読み取りと書き込みの間に独立性が生まれます。これは望ましいことかもしれません。

20GBRAM があちこちにある場合は、名前付きパイプの代わりにメモリ マップト一時ファイルを使用するとパフォーマンスが向上する可能性があります。

于 2013-05-29T15:44:50.720 に答える
3

違いが何であるかを確認するために、たくさんのファイルを含むファイルを作成しました

a somewhat long string followed by a number: 0000001

10,000 行 (約 50MiB) を含み、シェルの読み取りループを実行しました

while read line ; do
  echo $line | grep '00$' | cut -d " " -f9 | sed 's/^00*//'
done < data > data.out

これには約6分かかりました。同等品との比較

grep '00$' data | cut -d " " -f9 | sed 's/^00*//' > data.fast

0.2秒かかりました。フォークのコストを削減するために、私はテストしました

while read line ; do
  :
done < data > data.null

where:は何もしない組み込みのシェルです。予想どおりdata.null内容がなく、小さなファイルをループするのに 21 秒かかりました。20GB の入力ファイルに対してテストしたかったのですが、私はそれほど辛抱強くありません。

結論:これを書いている間に投稿したスクリプトを使用しようとすると、使用方法を学ぶか、awk永遠に待つことになるからです。perl

于 2013-05-29T16:45:19.667 に答える