私は大きなファイルで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でバッファリングしてsed
4kbをバッファリングすると、最後のバッファはpv
常に入力より8kb遅れます。その数値はそれよりはるかに高い可能性が高いです。
-u
GNU/BSD/ASTを使って切り替えることもできますが、sed
これはほぼ確実です。いいえ大規模入力のパフォーマンスを向上させるのに役立ちます。これを使用してsed
GNUを呼び出すと、入力のすべてのバイトをターゲットにし-u
ますread()
。私はこの状況で他の人がどのようにするのか見たことがありませんが、彼らが別の方法で行動すると信じる理由はありません。 3つのファイルすべての-u
意味バッファリングされていない- これは、ストリームに関して非常に一般的に理解される概念です。
あなたができるもう一つのことは明示的なラインバッファですsed
。出力w
riteコマンドと1つ以上の名前付きw
rite-file [s]を使用します。それでも速度は遅くなりますが、代わりに優れています。
sed
次の方法でこれを実行できます。
sed -n 'w outfile'
sed
ritew
コマンドは常に即時です。バッファリングされていない出力があります。だから(基本的に) sed
行サイクルごとにコマンドを1回適用すると、sed
パイプライン中に効率的な行バッファリングI / Oを簡単に使用できます。これにより、少なくとも次のように、pv
2番目の項目を常に最新の状態に保つことができますsed
。
pv ... | sed -n '24629045,24629162!w /dev/fd/1' | pv ...
/dev/fd/[num]
...リンクを提供するシステムがあると仮定しても(つまり、Androidを除くほぼすべてのLinuxベースのシステムと他にもたくさんあります)。そのリンクが利用できない場合、同じことを行うには、明示的に独自のパイプを作成し、mkfifo
それを最後の書き込みファイルpv
の標準入力として使用できます。sed
w