Ho una cartella che ha più di 250 file di 2 GB ciascuno. Ho bisogno di cercare una stringa/modello in quei file e produrre il risultato in un output
file. So di poter eseguire il seguente comando, ma è troppo lento!!
grep mypattern * > output
Voglio accelerare. Essendo un programmatore in Java, so che il multi-threading può essere utilizzato per accelerare il processo. Sono bloccato su come avviare grep
in "modalità multi-thread" e scrivere l'output in un singolo output
file.
Risposta accettata:
Ci sono due semplici soluzioni per questo. Fondamentalmente, usando xargs
o parallel
.
Approccio xargs:
Puoi usare xargs
con find
come segue:
find . -type f -print0 | xargs -0 -P number_of_processes grep mypattern > output
Dove sostituirai number_of_processes
dal numero massimo di processi che si desidera avviare.
Tuttavia, ciò non garantisce prestazioni significative nel caso in cui le prestazioni siano limitate all'I/O. In tal caso potresti provare ad avviare più processi per compensare il tempo perso in attesa degli I/O.
Inoltre, con l'inclusione di trova, puoi specificare opzioni più avanzate anziché solo modelli di file, come l'ora di modifica, ecc...
Un possibile problema con questo approccio, come spiegato dai commenti di Stéphane, se ci sono pochi file, xargs
potrebbe non avviare un numero sufficiente di processi per loro. Una soluzione sarà usare il -n
opzione per xargs
per specificare quanti argomenti dovrebbe prendere dalla pipe alla volta. Impostazione di -n1
forzerà xargs
per avviare un nuovo processo per ogni singolo file. Questo potrebbe essere un comportamento desiderato se i file sono molto grandi (come nel caso di questa domanda) e il numero di file è relativamente piccolo. Tuttavia, se i file stessi sono piccoli, il sovraccarico dovuto all'avvio di un nuovo processo può minare il vantaggio del parallelismo, nel qual caso un maggiore -n
il valore sarà migliore. Pertanto, il -n
l'opzione potrebbe essere ottimizzata in base alle dimensioni e al numero del file.
Approccio parallelo:
Un altro modo per farlo è usare lo strumento Ole Tange GNU Parallel parallel
, (disponibile qui). Ciò offre un maggiore controllo a grana fine sul parallelismo e può anche essere distribuito su più host (sarebbe utile se la tua directory fosse condivisa, ad esempio).
La sintassi più semplice che utilizza il parallelo sarà:
find . -type f | parallel -j+1 grep mypattern
dove l'opzione -j+1
indica in parallelo di avviare un processo in eccesso rispetto al numero di core sulla tua macchina (questo può essere utile per attività limitate di I/O, potresti anche provare a aumentare il numero).
Parallel ha anche il vantaggio su xargs
di mantenere effettivamente l'ordine dell'output di ciascun processo e di generare un output contiguo. Ad esempio, con xargs
, se il processo 1 genera una riga, dire p1L1
, il processo 2 genera una riga p2L1
, il processo 1 genera un'altra riga p1L2
, l'output sarà:
p1L1
p2L1
p1L2
mentre con parallel
l'output dovrebbe essere:
p1L1
p1L2
p2L1
Di solito è più utile di xargs
uscita.