現在、grepの使用中に「パフォーマンスの問題」に直面しています。私は多くの(Linuxカーネルリポジトリのサイズを考えてみてください)ファイルに多くの(10,000を超える)キーワードが表示されることを見つけようとしています。目標は、キーワードごとに1種類のインデックスを作成することです。
keyword: my_keyword
filepath 1
filepath 2
------
keyword: my_keyword2
...
私はシェルスクリプトに初めて触れたので、次のような簡単なことを試しました。
while read LINE; do
echo "keyword: "$LINE >> $OUTPUT_FILE
grep -E -r --include='Makefile*' "($LINE)" . >> "$OUTPUT_FILE"
echo "-----"
done < $KEYWORD_FILE
これを完了し、所望の結果を得るのに約45分かかります。
注:私が検索するすべてのキーワードは1つのファイル(「KEYWORD_FILE」なので開始する前に変更されています)にあり、検索を開始する前に検索するファイルを決定できます。検索する前に、検索するファイルのリストを次のように保存してみました。
file_set=( $(find . -name "Kbuild*" -o -name "Makefile*") )
次に、grep呼び出しを次のように置き換えます。
echo {$file_set[*]} | parallel -k -j+0 -n 1000 -m grep -H -l -w "\($LINE\)" >> "$OUTPUT_FILE"
完了するのに約1時間かかります...
質問:sh仕様に準拠している限り、必要なスキルを使用できることを考えると、これをどのように「より速く」および/またはより効率的に実行できますか?
たぶんgrep
使用されたツールではなく、私がparallel
間違って使用しているかもしれません...どんなアイデアでも大歓迎です!
答え1
答え2
私は10,000個のキーワードをつかみ、各ファイルを読み、各行でそれらのいくつかが一致することを確認するPerlスクリプト(例えば、現在Pythonがより人気があることを知っています...)を作成します。一致するものがあれば、キーの下にファイル/行として保存します(ここではハッシュが正しく機能します)。グループの完成後にハッシュを確認し、各キーワードの結果を出力します。
Perl(およびPython)は(半分)コンパイルされた言語であり、スクリプトは内部表現(非常にコンパクトで素早く解釈しやすい)でコンパイルされ、この内部形式は(一部)「最適化プログラム」で優先されます。速度は直接最適化したCと同じではありませんが、10倍遅くしてはいけません。
最後に、上記のコメントは次のとおりです。あなたの時間(作成、デバッグまたは取得、構築、使用方法の学習)はたくさん機械時間よりも価値があります(一晩置いておけば午後10時や午前6時に終わっても誰が気にしますか…)。
答え3
grep に -f および -F スイッチを使用すると、作業速度が速くなることがあります。グレブ缶かなり賢い複数パターンマッチング処理について
目標は、各キーワードのインデックスを作成することです。
それでは、解決策は検索エンジン(mnogoなど)ですか?
答え4
私は次のことを考えました。
- 各キーワードに対して、各ファイルを一度深刻にgrepすることはできません。その後、
-l / --files-with-matches
各ファイルが終了するまで無駄にgrepすることはできません。残念ながら(私が知っている限り)いくつかのモードの組み合わせはありません--files-with-matches
(少なくとも必要な方法ではありません)。これはawkで行うことができます。 awkは再帰的に(AFAIK)呼び出すことはできませんが、多数のファイルを検索することで呼び出すことができます。 - 私の経験では、まずfindを使用してツリーをナビゲートすると、多くのファイル(またはそのインデックスノード)にアクセスする速度が大幅に高速化される可能性があります。ディレクトリエントリとinodeがブロック単位で読み取られ、メタデータがキャッシュされるため、ディスクヘッドの移動が大幅に減ると思います。 findにフルパスを印刷させないでください。
-printf .
それで十分です。出力を/dev/nullに書き込みます。 - 最速の解決策は、シェルツールに依存せずにコンパイルされるアイテム(JITを含むPython(編集:))を作成することです。これにより、I / O(--files-with-matches実装)とCPU(まだ一致しないキーワードのすべての行をテスト)を最適化し、同時に各インデックスファイルにファイルパスを追加できます(tmpfs?)。 ;各キーワードに対して1つのFDを予約します(キーワードが1000個未満であると仮定)。その後、ファイルをリンクするだけです。ルックアップキャッシュもこの方法で最適化できます。まず、一致するファイル名が1000個になるまでファイル名を読み、次に対応するinode(stat()ファイル)を読み、次にファイルを検索してから1000個の名前のインポートを読みます。