ksh93はとても高速ですか?


9

そのため、一般的に、私はsedテキスト処理、特に大きなファイルを探す傾向があり、通常はシェル自体でそのようなことを行うのを避けます。

しかし、それは変わるかもしれないと思います。私はあちこち見ていてman ksh、これに気づきました:

<#pattern     Seeks forward to the beginning of the
              next line containing pattern.

<##pattern    The same as <# except that  the  por
              tion  of  the file that is skipped is
              copied to standard output.

実世界の有用性に懐疑的だったので、試してみることにしました。やった:

seq -s'foo bar
' 1000000 >file

...次のような100万行のデータの場合:

1foo bar
...
999999foo bar
1000000

...そしてそれを次のsedように対抗しました:

p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"    
do </tmp/file eval "time ( $c )"
done | wc -l

したがって、両方のコマンドは最大999999fooバーを取得する必要があり、それらのパターンマッチング実装は、少なくとも各行の最初と最後を評価する必要があります。また、否定パターンに対して最初の文字を検証する必要があります。これは簡単なことですが...結果は期待したものではありませんでした。

( sed '/^[^0-8]99999.*bar/q' ) \
    0.40s user 0.01s system 99% cpu 0.419 total
( ksh -c ':<##@(~(E)^[^0-8]99999.*bar)' ) \
    0.02s user 0.01s system 91% cpu 0.033 total
1999997

kshここではEREとsedBREを使用します。ksh以前、シェルパターンで同じことを行いましたが、結果に違いはありませんでした。

とにかく、それはかなり重要な不一致です-10倍以上のkshパフォーマンスを発揮sedします。以前に、David Kornが彼自身のio libを書いてそれを実装することを読んだことがありますksh-おそらくこれは関連していますか?-しかし、私はそれについてほとんど何も知りません。シェルはこれをどのようにうまく行うのですか?

私にとってさらに驚くべきことはksh、あなたが尋ねるところに、そのオフセットを正しく残していることです。(GNU)から(ほぼ)同じものを取得するには、使用する必要があります- 非常に遅い sed-u

ここにgrepv。kshテストがあります:

1000000         #grep + head
( grep -qm1 '^[^0-8]99999.*bar'; head -n1; ) \
    0.02s user 0.00s system 90% cpu 0.026 total
999999foo bar   #ksh + head
( ksh -c ':<#@(~(E)^[^0-8]99999.*bar)'; head -n1; )  \
    0.02s user 0.00s system 73% cpu 0.023 total

kshgrepここで打つ-それは常にではない-彼らはかなり結ばれています。それでも、それはかなり優れており、先読み ksh提供します- headの入力は、一致する前に始まります。

それは本当であるには余りにも良さそうだと思います。フードの下でこれらのコマンドはどのように異なっていますか?

ああ、どうやらここにはサブシェルすらありません:

ksh -c 'printf %.5s "${<file;}"'

あるpattern正規表現または単純なシェルのパターン?
muru

@muru-どちらでもかまいませんが、私はそれらを変えるのがあまり得意ではありません。この例では、シェルパターン(デフォルト)です。
mikeserv 2014

@muru-正規表現で1つ追加しました。
mikeserv 2014

回答:


8

kshはsfioを使用するだけでなく、独自のカスタムメモリアロケーターを使用します。

それにもかかわらず、私の推測ではsfioがこのケースで違いを生むと思います。私はあなたの例をstraceの下で実行しようとしたところ、kshが読み取り/書き込みを200回(65 KBブロック)呼び出しているのに対して、sedは3400回(4 KBブロック)呼び出していることがわかります。sed -uを使用すると、ラップトップがほとんど溶けて、バイトごとに読み取りが行われ、行ごとに書き込まれます。Ksh simpleはlseekを使用しています。Grepは読み取りを400回まで使用します(32 KBブロック)。


ええ-バッファリングされていないのは、気の弱い人には向いていません。場合、私は疑問に思うkshの正規表現エンジンがそのIOとして効率的ですか?とにかく、答えてくれてありがとう。あなたのラップトップに私の謝罪。しかし、カスタムメモリアロケータはどうですか?もう何かありますか?
mikeserv 2014

1
残念ながら、違います。もちろん、ソースコードをat&tウェブサイトからダウンロードすることもできますが、それだけです。このライブラリはASTと呼ばれ、アロケーター、正規表現エンジン、その他多くのものが含まれています。したがって、これらすべてを組み合わせるとkshがはるかに高速になる可能性は十分にあります。
ミロスラフフラン


ありがとうございます。これも有望に見えます。ASTソフトウェアコレクションで利用できるコンポーネントの一部は次のとおりです。POSIXコマンド標準のPOSIXコマンドのほとんどは、ASTコレクションで利用できます。多くは、組み込み関数としてkshに追加できるライブラリー関数としてコーディングされており、パフォーマンスが劇的に向上します。-今、私はそれを構築する方法を理解しなければなりません
mikeserv

1
@mikeserv kshは、Phong Voのvmallocアロケーターを使用するように構築できます。そのリンクで利用できるジャーナル記事。
Mark Plotnick、2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.