Etwas schneller als grep?

11262
Jeffrey L. Roberts

Ich bin auf der Suche nach einem Werkzeug, das schneller als grep ist, vielleicht ein multi-thread-grep oder etwas ähnliches.

Ich habe ungefähr 100 Millionen Textdateien, die ich für exakte Übereinstimmungen mit Zeichenfolgen benötigen. Wenn ich eine Übereinstimmung gefunden habe, benötige ich den Dateinamen, unter dem die Übereinstimmung gefunden wurde.

ie: grep -r 'exact match' > filepaths.log 

Es sind ungefähr 4 TB an Daten, und ich habe meine erste Suche vor 6 Tagen gestartet, und grep läuft noch. Ich habe noch ein Dutzend Suchanfragen und ich kann nicht zwei Monate warten, um alle diese Dateinamen abzurufen =]

Ich habe die folgenden Punkte überprüft, aber ich glaube nicht, dass ich alle Glocken und Trillerpfeifen brauche, die diese Indexer mitbringen.

  • dtSearch
  • Terrier
  • Lucene
  • Xapian
  • Rückstoß
  • Sphinx

und nachdem ich stundenlang über all diese Engines gelesen hatte, dreht sich mein Kopf und ich wünschte, ich hätte ein Multi-Threaded-Grep-Lol, alle Ideen und / oder Vorschläge werden sehr geschätzt!

PS: Ich verwende CentOS 6.5

BEARBEITEN: Die Suche nach Multithread-grep gibt mehrere Elemente zurück. Meine Frage ist: Ist ein Multithread-Grep die beste Option für das, was ich mache?

EDIT2: Nach ein paar Änderungen habe ich mir das ausgedacht und es geht viel schneller als das reguläre grep. Ich wünschte mir immer noch, es wäre schneller ... Ich beobachte meine Festplatte und warte, und es baut sich noch nicht auf, Ich kann noch ein paar Änderungen vornehmen und bin trotzdem an weiteren Vorschlägen interessiert =]

find . -type f -print0 | xargs -0 -n10 -P4 grep -m 1 -H -l 'search string' 
1
Du hast also vor, nach mehr als einer Saite zu suchen, oder? Multithreading ist nicht hilfreich, da Sie durch den Datenträger-Durchsatz und (was noch wichtiger ist) die Suchleistung einschränken. Daniel B vor 9 Jahren 0
ya, die Festplatten sind hier der Engpass Jeffrey L. Roberts vor 9 Jahren 0
"100 Millionen Textdateien" ... wirklich? und der Ansatz, um wirklich alles zu ergreifen, hängt davon ab, ob dies eine einmalige Sache ist oder ob die Daten wirklich für die zukünftige Verwendung indiziert werden müssen. Tyson vor 9 Jahren 0
ya ... wirklich. lol =] Es ist mehr oder weniger eine einmalige Sache für insgesamt etwa zwei Dutzend Suchanfragen Jeffrey L. Roberts vor 9 Jahren 0

2 Antworten auf die Frage

9
Kenster

grepist E / A-gebunden, dh die Geschwindigkeit hängt davon ab, wie schnell die gesuchten Dateien gelesen werden können. Mehrere parallele Suchvorgänge können miteinander um Festplatten-E / A konkurrieren, sodass Sie möglicherweise nicht viel beschleunigen.

Wenn Sie nur übereinstimmende Dateinamen und nicht die tatsächlich gefundenen Übereinstimmungen in den Dateien benötigen, sollten Sie grep mit dem -lFlag ausführen . Dieses Flag bewirkt, dass grep nur übereinstimmende Dateinamen und nicht die übereinstimmenden Zeilen druckt. Der Wert hier ist, dass es grep erlaubt, die Suche nach einer Datei zu beenden, sobald eine Übereinstimmung gefunden wurde. Dadurch könnte der Arbeitsaufwand für grep reduziert werden.

Wenn Sie nach festen Zeichenfolgen statt nach regulären Ausdrücken suchen, können Sie versuchen, fgrepstatt zu verwenden grep. Fgrep ist eine Variante von grep, die nach festen Zeichenfolgen sucht. Die Suche nach festen Zeichenfolgen ist schneller als die Suche nach regulären Ausdrücken. Möglicherweise sehen Sie hier keine Verbesserung, da moderne Versionen von grep wahrscheinlich klug genug sind, die Suche nach festen Zeichenfolgen trotzdem zu optimieren.

Wenn Sie mehrere Suchvorgänge parallel ausführen möchten, können Sie dies mit Hilfe von Shell-Dienstprogrammen tun. Eine Möglichkeit wäre, eine Liste von Dateinamen zu erstellen, sie in Teile zu teilen und grep für jede Liste separat auszuführen:

find /path/to/files -type f -print | split -l 10000000 list. for file in list.*; do grep -f $ -l 'some text' > $.out & done wait cat $*.out > filepaths.log rm list.* 

Dabei werden finddie Dateien gesucht, die Liste der Dateinamen in zehn Millionen Gruppen aufgeteilt und für jede Gruppe parallel ausgeführt. Die Ausgabe der Greps wird am Ende alle miteinander verbunden. Dies sollte für Dateien mit typischen Namen funktionieren, würde aber für Dateien mit Zeilenumbrüchen beispielsweise fehlschlagen.

Ein anderer Ansatz verwendet xargs. Zuerst müssen Sie ein einfaches Shell-Skript schreiben, das im Hintergrund grep ausführt:

#!/bin/bash grep -l 'search text' "$@" >> grep.$$.out & 

Dadurch wird grep in der Liste der Dateien ausgeführt, die als Argumente für das Skript angegeben wurden. Das Ergebnis wird in eine Datei geschrieben, die nach der PID des Prozesses benannt ist. Der grep-Prozess läuft im Hintergrund ab.

Dann würden Sie das Skript so ausführen:

find /path/to/files -type f -print0 | xargs -0 -r /my/grep/script [ wait for those to finish ] cat grep.*.out > filepaths.log rm grep.*.out 

In diesem Fall xargswerden die Dateinamen in Gruppen zusammengefasst und das Skript für jede Gruppe einmal ausgeführt. Das Skript führt für jede Gruppe einmal eine Instanz von grep aus. Sobald alle grep-Instanzen abgeschlossen sind, können Sie deren Ausgaben kombinieren. Leider konnte ich mir keine clevere Möglichkeit vorstellen, automatisch auf die Grep-Instanzen zu warten, um hier fertig zu werden. Daher müssen Sie dies möglicherweise manuell tun.

Wenn Sie keinen regulären Ausdruck benötigen, ist ein Vorteil von `fgrep ', dass Sie sich keine Sorgen um reservierte Zeichen machen müssen, z. B.` fgrep' .. '`anstelle von' grep '\. \.'`. thdoan vor 7 Jahren 0
0
Kristian

Klingt nach einem Skript oder einem kleinen Programm, das mehrere Instanzen ausführt (dh 8 x grep könnten auf einem modernen i7 mit 4 Kernen / 8 Threads parallel ausgeführt werden) von grep und die Ausgabe verketten oder zusammenführen, mehr als Sie einen schnelleren grep benötigen .

Wie man ein solches Skript erstellt, ist eine ganz andere Frage, aber so würde ich dein Problem angreifen.

Wenn sich Dateien auf mehreren Laufwerken befinden, ist dies zwar IO-gebunden, nicht CPU-gebunden. Christophe Roussy vor 6 Jahren 0