可能な限り最速のgrep


80

grepできるだけ早くするためのヒントがあるかどうか知りたいのですが。私は可能な限り迅速な方法で検索するためにかなり大きなテキストファイルのベースを持っています。-iオプションを取り除くことができるように、すべて小文字にしました。これにより、検索がはるかに高速になります。

また、私はことを発見した-F-Pモードが速く、デフォルトよりもあります。検索文字列が正規表現ではない場合(プレーンテキストのみ)は前者を使用し、正規表現が含まれる場合は後者を使用します。

誰かがスピードアップの経験がありgrepますか?たぶん、特定のフラグを使用して最初からコンパイルしたり(Linux CentOSを使用しています)、特定の方法でファイルを整理したり、何らかの方法で検索を並行させたりしますか?


1
これは常に同じファイルのセットですか?同じ(大きな)ファイルのセットをで検索していることに気付いた場合はgrep、それらを適切にインデックス付けするための解決策を探すときが来たかもしれません(「最良の」解決策は、これらのファイルの種類によって異なります)。
fatalError 2012年

はい、それは同じファイルのセットです。luceneのようなフルテキストソリューションがパフォーマンスを向上させると思いますか?一般に、2500ファイル(各文学書)を検索して合計約2億5000万語の単語数を検索するには、約30/40秒かかります。
ピスタチオ2012年

1
"...or maybe make the search parallel in some way?"私はこれについて聞いて本当に興奮しています。 grep完全に並行して動作できるはずですが、検索はまだI / Oバウンドである可能性があります。
Conrad.Dean 2012年

2
使ってみましたack-grepか?
meder omuraliev 2012年

2
ack-grepより良いAgを使用してください!geoff.greer.fm/2011/12/27/the-silver-searcher-better-than-ack
ニコラスウィルソン

回答:


104

GNU parallelを試してみてください。これには、以下での使用方法の例がgrep含まれいます。

grep -rディレクトリを再帰的にgrepsします。マルチコアCPUでは、GNU parallelはこれを高速化できることがよくあります。

find . -type f | parallel -k -j150% -n 1000 -m grep -H -n STRING {}

これにより、コアごとに1.5ジョブが実行され、に1000個の引数が与えられgrepます。

大きなファイルの場合、--pipeand--block引数を使用して入力をいくつかのチャンクに分割できます。

 parallel --pipe --block 2M grep foo < bigfile

SSHを介して複数の異なるマシンで実行することもできます(パスワードを回避するためにssh-agentが必要です)。

parallel --pipe --sshlogin server.example.com,server2.example.net grep foo < bigfile

5
--color=alwaysgrepの色を保持するために使用します(これは、パイプでgrepを使用している場合にも当てはまります)
Jim

2
述語findがある場合-print0(ほとんどの場合)、を使用することをお勧めしますfind . -type f -print0 | parallel -0 -k …。私のインスタンスはman(1) parallel実際にこれを言っています。また、私はと疑うglobstarあなたが特定のファイルパターン後にしている場合は、これをさらに高速化することができます:shopt -s globstar; parallel -k -j150% -n 1000 -m fgrep -H -n STRING ::: **/*.c
幸次郎

3
それは有用な使用だ@WilliamPursellcatしたい場合はsudo、アクセスするbigfile
Jayen

2
コアごとに1.5ジョブを設定するのはなぜですか?コアごとに1つのジョブを使用しないのはなぜですか?
JohnGalt 2016

2
@JohnGalt多くの場合、ディスクI / Oはプロセスの1つを停止します。コアよりもいくつかを開始することで、いくつかのジョブがデータを待機している場合でも、すべてのコアに対して実行することがまだあります。150%を調整して、システムで最適に機能するものを確認します。
オレタンゲ2017

70

非常に大きなファイルを検索している場合は、ロケールを設定すると非常に役立ちます。

GNU grepは、UTF-8よりもCロケールの方がはるかに高速です。

export LC_ALL=C

1
印象的で、この1本の線が2倍の速度を与えるように見えます。
Fedir RYKHTIK 2013

誰かがこれがなぜであるか説明できますか?
Robert E Mealey 2014

5
「単純なバイト比較と複数バイトの文字比較」<私の上司は言う...右右右
Robert E Mealey 2014

7
したがって、これは完全に安全ではありません。特に、(文字列マッチングだけでなく)パターンマッチングを行っている場合、またはファイルのコンテンツがASCIIでない場合はそうです。それでも場合によっては行う価値がありますが、注意してください。
Robert E Mealey 2014

@RobertEMealey彼は「シンプル」ではなく「シングル」と言いましたか?
Elijah Lynn

12

Ripgrepは今や最速だと主張しています。

https://github.com/BurntSushi/ripgrep

デフォルトで並列処理も含まれます

 -j, --threads ARG
              The number of threads to use.  Defaults to the number of logical CPUs (capped at 6).  [default: 0]

READMEから

これは、Rustの正規表現エンジンの上に構築されています。Rustの正規表現エンジンは、有限オートマトン、SIMD、および積極的なリテラル最適化を使用して、検索を非常に高速にします。


これは信じられないほど速いです!
2017


4

厳密にはコードの改善ではありませんが、2百万以上のファイルでgrepを実行した後に役立つことがわかりました。

操作を安価なSSDドライブ(120GB)に移しました。定期的に大量のファイルを処理している場合は、約100ドルで手頃な価格のオプションです。


3

どのファイルに文字列が含まれているかを気にしない場合は、読み取りgrepを2つのジョブに分割することをお勧めgrepます。これは、小さなファイルごとに1回ずつ、何度も生成するのにコストがかかる可能性があるためです。

  1. 非常に大きなファイルが1つある場合:

    parallel -j100% --pipepart --block 100M -a <very large SEEKABLE file> grep <...>

  2. 多くの小さな圧縮ファイル(iノードでソート)

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j80% --group "gzcat {}" | parallel -j50% --pipe --round-robin -u -N1000 grep <..>

私は通常、スループットを最大化するためにファイルをlz4で圧縮します。

  1. 一致するファイル名だけが必要な場合:

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j100% --group "gzcat {} | grep -lq <..> && echo {}


2

Sandroの回答に基づいて、彼がここで提供したリファレンスを見て、BSDgrepとGNUgrepを試してみました。私の簡単なベンチマーク結果は次のことを示しています。GNUgrepははるかに高速です。

したがって、元の質問「可能な限り最速のgrep」に対する私の推奨事項:BSD grep(たとえば、MacOSのデフォルト)ではなくGNUgrepを使用していることを確認してください。


250MBの.sqlダンプファイルを検索しているときに、13
インチMacBookProで

2

私は個人的にgrepの代わりにag(シルバーサーチャー)を使用していますが、それははるかに高速であり、並列およびパイプブロックと組み合わせることができます。

https://github.com/ggreer/the_silver_searcher

更新:ユースケースによっては、agよりも高速なhttps://github.com/BurntSushi/ripgrepを使用するようになりました。


これにバグを見つけました。時々それはツリーの奥深くには行かず、grepは結果を表示しますが、agは表示しない場合があります。速度の精度について妥協することはできません。
username_4567

1
今まで私は不正確さを見つけなかったので、あなたは彼らのgithubアカウントでIssueを開いてそれを報告するべきです(私はそれをしますが、それを複製することはできません)。確かに彼らはこれを整理するでしょう、そしてそうですあなたは正しいです私は完全に同意します:最初に正確さ。
Jinxmcg 2016年

1

grepを使用して(特にパターンを変更するために)単一の大きなファイルを検索する方が速いことがわかったのは、並列フラグとともにsplit + grep + xargsを使用することです。例えば:

my_ids.txtという大きなファイルに検索したいIDのファイルがあるbigfileの名前bigfile.txt

splitを使用して、ファイルをパーツに分割します。

# Use split to split the file into x number of files, consider your big file
# size and try to stay under 26 split files to keep the filenames 
# easy from split (xa[a-z]), in my example I have 10 million rows in bigfile
split -l 1000000 bigfile.txt
# Produces output files named xa[a-t]

# Now use split files + xargs to iterate and launch parallel greps with output
for id in $(cat my_ids.txt) ; do ls xa* | xargs -n 1 -P 20 grep $id >> matches.txt ; done
# Here you can tune your parallel greps with -P, in my case I am being greedy
# Also be aware that there's no point in allocating more greps than x files

私の場合、これにより、17時間の仕事が1時間20分の仕事になりました。ここには効率に関するある種のベルカーブがあると確信しており、明らかに利用可能なコアを超えても何の役にも立ちませんが、これは上記の要件に対する上記のコメントよりもはるかに優れたソリューションでした。これには、ほとんど(Linux)のネイティブツールを使用する際に、スクリプトと並行して使用する場合に比べて追加の利点があります。


0

cgrepが利用可能な場合、grepよりも桁違いに高速になる可能性があります。


0

MCE 1.508には、多くのCバイナリをサポートするデュアルチャンクレベルの{file、list}ラッパースクリプトが含まれています。agrep、grep、egrep、fgrep、およびtre-agrep。

https://metacpan.org/source/MARIOROY/MCE-1.509/bin/mce_grep

https://metacpan.org/release/MCE

-iを高速に実行したい場合は、小文字に変換する必要はありません。--lang = Cをmce_grepに渡すだけです。

出力順序は保持されます。-nおよび-bの出力も正しいです。残念ながら、このページで説明されているGNUパラレルには当てはまりません。私はGNUParallelがここで機能することを本当に望んでいました。さらに、バイナリを呼び出すときに、mce_grepはサブシェル(sh -c / path / to / grep)を実行しませ

もう1つの代替手段は、MCEに含まれているMCE :: Grepモジュールです。


上記のツールの作成者である免責事項を提供する必要があります。
FractalSpace 2018年

0

元のトピックからのわずかな逸脱:googlecodesearchプロジェクトのインデックス付き検索コマンドラインユーティリティは、grepよりもはるかに高速です:https//github.com/google/codesearch

コンパイルしたら(golangパッケージが必要です)、次のコマンドでフォルダーにインデックスを付けることができます。

# index current folder
cindex .

インデックスは下に作成されます ~/.csearchindex

今、あなたは検索することができます:

# search folders previously indexed with cindex
csearch eggs

色付きの一致を取得するために、まだ結果をgrepにパイプしています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.