大きなファイルでsedを実行し、 pv ユーティリティを使用して、入力の読み取りと出力の書き込みの速度を確認しました。 pvは、sedが約5秒以内に入力を読み取り、出力を書き込んだことを示しましたが、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] [ <=> ]
2つの理由があります。そもそも、q
uitには伝えません。
考えてみましょう:
_seq 10 | sed -ne1,5p
_
その場合、入力行の前半をp
rintするだけですが、残りの行をEOFまで読み取る必要があります。代わりに:
_seq 10|sed 5q
_
すぐに終了します。
また、各プロセスの間に遅延があります。したがって、pv
が4kbでバッファリングし、sed
が4kbをバッファリングする場合、最後のpv
は入力より8kb遅れます。その数はそれよりも多い可能性が高いです。
GNU/BSD/AST sed
を使用して_-u
_スイッチを試すことができますが、それはほぼ間違いなくnotは役に立ちません大きな入力でのパフォーマンス。 GNU sed
with _-u
_を呼び出すと、入力のすべてのバイトに対してread()
になります。他のオブジェクトについては調べていません。そのような状況で行いますが、私はそれらが異なることをすると信じる理由はありません.3つのドキュメントすべて_-u
_はunbufferedを意味します-そしてそれはストリームが関係する、かなり一般的に理解されている概念。
あなたがするかもしれないもう一つのことは、sed
riteコマンドと1つ以上で明示的にラインバッファw
outputですw
rite-file [s]という名前。それでも少し遅くなりますが、おそらく他の方法よりも優れています。
これは、次のようなsed
を使用して実行できます。
_sed -n 'w outfile'
_
sed
のw
riteコマンドは常に即時です-バッファなしの出力です。また、(デフォルト)sed
はラインサイクルごとに1回コマンドを適用するため、sed
を簡単に使用して効果的に使用できますパイプラインの途中でもラインバッファI/O。そうすれば、少なくとも、次のように、2番目のpv
をsed
でほぼ最新の状態に保つことができます。
_pv ... | sed -n '24629045,24629162!w /dev/fd/1' | pv ...
_
...それは_/dev/fd/[num]
_リンクを提供するシステムを想定していますが(つまり、実質的にすべてのLinuxベースのシステム-Android -および 他にも多数 )上記のリンクの可用性に失敗した場合、同じことを行うには、mkfifo
とを使用して独自のパイプを明示的に作成できます。これを最後のpv
のstdinとして使用し、sed
のw
riteファイルとして名前を付けます。