出力を作成した後、sedがすぐに終了しないのはなぜですか?

出力を作成した後、sedがすぐに終了しないのはなぜですか?

私は大きなファイルでsedを実行しています。PV入力を読み、出力を書き込む速度を確認するユーティリティです。 pvは、約5秒以内にsedが入力を読み取り、出力を書き込むことを示しますが、sedは20〜30秒間終了しません。なぜこれですか?

私が見た結果は次のとおりです。

pv -cN source input.txt | sed "24629045,24629162d" | pv -cN output > output.txt
   source: 2.34GB 0:00:06 [ 388MB/s] [==========================================================================================================>] 100%            
   output: 2.34GB 0:00:05 [ 401MB/s] [              <=>                                                                                                           ]

答え1

2つの理由があります。まず、あなたはそれを言わなかったq

考慮する:

seq 10 | sed -ne1,5p

この場合、p入力ラインの最初の半分だけを印刷しますが、EOFまで入力ラインの残りの部分を読み取る必要があります。代わりに:

seq 10|sed 5q

すぐに終了します。

また、各プロセス間の待ち時間も処理する必要があります。したがってpv、4kbでバッファリングしてsed4kbをバッファリングすると、最後のバッファはpv常に入力より8kb遅れます。その数値はそれよりはるかに高い可能性が高いです。

-uGNU/BSD/ASTを使って切り替えることもできますが、sedこれはほぼ確実です。いいえ大規模入力のパフォーマンスを向上させるのに役立ちます。これを使用してsedGNUを呼び出すと、入力のすべてのバイトをターゲットにし-uますread()。私はこの状況で他の人がどのようにするのか見たことがありませんが、彼らが別の方法で行動すると信じる理由はありません。 3つのファイルすべての-u意味バッファリングされていない- これは、ストリームに関して非常に一般的に理解される概念です。

あなたができるもう一つのことは明示的なラインバッファですsed出力writeコマンドと1つ以上の名前付きwrite-file [s]を使用します。それでも速度は遅くなりますが、代わりに優れています。

sed次の方法でこれを実行できます。

sed -n 'w outfile'

sedritewコマンドは常に即時です。バッファリングされていない出力があります。だから(基本的に) sed行サイクルごとにコマンドを1回適用すると、sedパイプライン中に効率的な行バッファリングI / Oを簡単に使用できます。これにより、少なくとも次のように、pv2番目の項目を常に最新の状態に保つことができますsed

pv ... | sed -n '24629045,24629162!w /dev/fd/1' | pv ...

/dev/fd/[num]...リンクを提供するシステムがあると仮定しても(つまり、Androidを除くほぼすべてのLinuxベースのシステムと他にもたくさんあります)。そのリンクが利用できない場合、同じことを行うには、明示的に独自のパイプを作成し、mkfifoそれを最後の書き込みファイルpvの標準入力として使用できます。sedw

関連情報