grep
をできるだけ速くするためのヒントがあるかどうかを知りたい。できるだけ早く検索するためのテキストファイルのかなり大きなベースがあります。私はそれらをすべて小文字にしたので、-i
オプション。これにより、検索が非常に高速になります。
また、-F
および-P
モードはデフォルトよりも高速です。検索文字列が正規表現(単なるプレーンテキスト)でない場合は前者を使用し、正規表現が関係する場合は後者を使用します。
grep
を高速化した経験はありますか?特定のフラグ(Linux CentOSを使用)を使用してゼロからコンパイルしたり、特定の方法でファイルを整理したり、何らかの方法で検索を並列にしたりできますか?
GNU parallel を試してください。これには grep
での使用方法の例 が含まれます。
grep -r
はディレクトリを再帰的に検索します。マルチコアCPUでは、GNUparallel
はこれを高速化できます。find . -type f | parallel -k -j150% -n 1000 -m grep -H -n STRING {}
これにより、コアあたり1.5ジョブが実行され、
grep
に1000個の引数が与えられます。
大きなファイルの場合、--pipe
および--block
引数を使用して、入力をいくつかのチャンクに分割できます。
parallel --pipe --block 2M grep foo < bigfile
また、SSHを介して複数の異なるマシンで実行することもできます(パスワードを回避するには、ssh-agentが必要です)。
parallel --pipe --sshlogin server.example.com,server2.example.net grep foo < bigfile
非常に大きなファイルを検索する場合は、ロケールを設定すると本当に役立ちます。
GNU grepは、UTF-8を使用する場合よりもCロケールを使用した場合の方がはるかに高速です。
export LC_ALL=C
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、および積極的なリテラル最適化を使用して、検索を非常に高速にします。
どうやら--mmapを使用すると、一部のシステムで役立ちます。
http://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html
厳密にはコードの改善ではありませんが、2,000,000個のファイルに対してgrepを実行した後に役立つことがわかりました。
安価なSSDドライブ(120GB)に操作を移動しました。約100ドルで、大量のファイルを定期的に処理する場合、手頃な価格のオプションです。
どのファイルに文字列が含まれているかを気にしない場合は、readingとgrepping2つのジョブに分割します。これは、grep
を何度も(小さなファイルごとに1回)生成するのにコストがかかる可能性があるためです。
非常に大きなファイルが1つある場合:
parallel -j100% --pipepart --block 100M -a <very large SEEKABLE file> grep <...>
多くの小さな圧縮ファイル(inodeでソート)
ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j80% --group "gzcat {}" | parallel -j50% --pipe --round-robin -u -N1000 grep <..>
スループットを最大にするため、通常はファイルをlz4で圧縮します。
一致するファイル名のみが必要な場合:
ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j100% --group "gzcat {} | grep -lq <..> && echo {}
Sandroの回答に基づいて、私は彼が提供したリファレンスを参照しました here BSD grep vs. GNU grep。私の簡単なベンチマークの結果は、次のとおりです。GNU grepは、はるかに高速です。
したがって、元の質問「最速のgrep」に対する私の推奨事項:BSD grep(MacOSのデフォルトなど)ではなくGNU grepを使用していることを確認してください。
私は個人的にgrepの代わりにag(シルバーサーチャー)を使用しています。これはずっと高速です。また、並列ブロックやパイプブロックと組み合わせることができます。
https://github.com/ggreer/the_silver_searcher
更新:私は https://github.com/BurntSushi/ripgrep を使用するようになりました。これは、ユースケースによってはagよりも高速です。
1つの大きなファイルでgrepを使用して(特にパターンを変更するために)grepを使用して高速に検索できることの1つは、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)ネイティブツールを使用する際に、スクリプトと比較して利点があります。
cgrepが利用可能であれば、grepよりも桁違いに高速です。
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パラレルの場合はそうではありません。 GNU Parallelがここで動作することを本当に望んでいました。さらに、mce_grepは、バイナリを呼び出すときにサブシェル(sh -c/path/to/grep)をnotします。
別の代替手段は、MCEに含まれているMCE :: Grepモジュールです。
元のトピックからのわずかな逸脱:googlecodesearchプロジェクトのインデックス付き検索コマンドラインユーティリティは、grepよりもはるかに高速です。 https://github.com/google/codesearch :
コンパイルしたら( golang パッケージが必要です)、フォルダーのインデックスを作成できます:
# index current folder
cindex .
インデックスは~/.csearchindex
の下に作成されます
これで検索できます:
# search folders previously indexed with cindex
csearch eggs
私はまだ色分けされた一致を得るためにgrepを通して結果をパイプしています。