Qualcosa di più veloce di grep? [chiuso]


4

Sto cercando uno strumento che sarà più veloce di grep, forse un grep multi-thread o qualcosa di simile ... Ho cercato un sacco di indicizzatori, ma non sono stato venduto e ho bisogno di un indice ...

Ho circa 100 milioni di file di testo, che ho bisogno di grep per corrispondenze esatte di stringhe, quando trovo una corrispondenza di stringhe, ho bisogno del nome del file in cui è stata trovata la corrispondenza.

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

Sono circa 4 TB di dati e ho iniziato la mia prima ricerca 6 giorni fa e grep è ancora in esecuzione. Ho ancora una dozzina di ricerche da fare e non posso aspettare 2 mesi per recuperare tutti questi nomi di file =]

Ho esaminato quanto segue, tuttavia, non penso di aver bisogno di tutte le campane e fischietti che vengono con questi indicizzatori, ho solo bisogno del nome del file in cui si è verificata la corrispondenza ...

  • dtSearch
  • Terrier
  • Lucene
  • Xapian
  • Rinculo
  • Sfinge

e dopo aver passato ore a leggere su tutti quei motori, mi gira la testa e vorrei solo avere un grep lol multi-thread, qualsiasi idea e / o suggerimento sono molto apprezzati!

PS: utilizzo CentOS 6.5

EDIT: La ricerca di grep multi-thread restituisce diversi elementi, la mia domanda è: un grep multi-thread è l'opzione migliore per quello che sto facendo?

EDIT2: Dopo alcune modifiche, questo è quello che ho escogitato, e sta andando molto più veloce del grep normale, vorrei ancora che fosse più veloce però ... Sto guardando il mio disco, aspetto, e non si sta ancora accumulando , Potrei fare qualche altra modifica, e sicuramente ancora interessato a qualsiasi suggerimento =]

find . -type f -print0 | xargs -0 -n10 -P4 grep -m 1 -H -l 'search string'

Quindi hai davvero intenzione di cercare più di una stringa, giusto? Il multithreading non aiuta perché sei limitato dalla velocità del disco e (soprattutto) cerca prestazioni.
Daniel B,

Sì, i dischi hanno sicuramente il collo di bottiglia qui
Jeffrey L. Roberts,

"100 milioni di file di testo" ... davvero? e l'approccio da adottare dipende davvero dal fatto che si tratti di una cosa sola o che i dati debbano davvero essere indicizzati per un uso futuro.
Tyson,

ya ... davvero. lol =] È più o meno una volta una cosa per circa 2 dozzine di ricerche in totale
Jeffrey L. Roberts,

Risposte:


10

grepè associato all'I / O, il che significa che la sua velocità è dominata dalla velocità con cui può leggere i file che sta cercando. Più ricerche in parallelo possono competere tra loro per l'I / O del disco, quindi potresti non vedere molta velocità.

Se hai solo bisogno di nomi di file corrispondenti e non delle corrispondenze effettive trovate nei file, allora dovresti eseguire grep con il -lflag. Questo flag fa in modo che grep stampi solo i nomi dei file corrispondenti e non le linee corrispondenti. Il valore qui è che consente a grep di interrompere la ricerca di un file una volta che ha trovato una corrispondenza, quindi potrebbe ridurre la quantità di lavoro che grep deve fare.

Se stai cercando stringhe fisse anziché espressioni regolari, puoi provare a utilizzare fgrepanziché grep. Fgrep è una variante di grep che cerca stringhe fisse e la ricerca di stringhe fisse è più veloce dell'esecuzione di una ricerca di espressioni regolari. Potresti vedere qualche miglioramento da questo, perché le versioni moderne di grep sono probabilmente abbastanza intelligenti da ottimizzare comunque le ricerche a stringa fissa.

Se si desidera provare a eseguire più ricerche in parallelo, è possibile farlo utilizzando le utilità della shell. Un modo sarebbe quello di costruire un elenco di nomi di file, dividerlo in parti ed eseguire grep separatamente per ogni elenco:

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

Questo utilizza findper trovare i file, suddivide l'elenco dei nomi di file in gruppi di dieci milioni ed esegue grep in parallelo per ciascun gruppo. L'output dei greps sono tutti uniti alla fine. Questo dovrebbe funzionare per file con nomi tipici, ma fallirebbe per i file che avevano una nuova riga nei loro nomi, ad esempio.

Un altro approccio utilizza xargs. Innanzitutto, dovresti scrivere un semplice script di shell che esegue grep in background:

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

Questo eseguirà grep nell'elenco dei file specificati come argomenti nello script, scrivendo il risultato in un file chiamato dopo il PID del processo. Il processo grep viene eseguito in background.

Quindi eseguiresti lo script in questo modo:

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 questo caso, xargsraggrupperà i nomi dei file in gruppi ed eseguirà lo script una volta per ciascun gruppo. Lo script eseguirà un'istanza di grep una volta per ciascun gruppo. Una volta terminate tutte le istanze di grep, è possibile combinare i relativi output. Sfortunatamente, non riuscivo a pensare a un modo intelligente per aspettare automaticamente che le istanze grep finissero qui, quindi potresti doverlo fare manualmente.


Se non hai bisogno di regex, uno dei vantaggi fgrepè che non devi preoccuparti di sfuggire ai personaggi riservati, ad esempio fgrep '..'invece di grep '\.\.'.
thdoan

Grep non è sempre associato a I / O. Attualmente sto eseguendo un grep associato alla CPU.
iAdjunct

0

Sembra che tu abbia bisogno di uno script o di un piccolo programma che eseguirà più istanze (ovvero 8 x grep potrebbero essere eseguiti in parallelo su un moderno i7 con 4 core / 8threads) di grep e concatenare o unire l'output, più di quanto tu abbia bisogno di un grep più veloce .

Come realizzare una sceneggiatura del genere è un'altra domanda, ma è così che attaccerei il tuo problema.


Se i file si trovano su più unità forse, ma questo è associato a IO, non a CPU.
Christophe Roussy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.