[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Curiosità grep



Alle giovedì 20 settembre 2007, Andrea Barbaglia ha scritto:
> Ciao a tutti,
Ciao!
>
> mentre giocavo qua è la con la shell, un dubbio atroce
> mi si è infilato in testa riguardo la velocità di
> grep...
E' una Buona Domana :-p
> Mettiamo che abbia un file di testo di dimensioni
> considerevoli, vicine o superiori al giga.
> Voglio cercare all'interno di tale file una parola...
[snip]
Un buon test vale piu' di 1000 parole!
Ecco allora un po' di semplici test che ho fatto su un file di mail da 198MB: 
(grandezza molto inferiore al giga, ma comunque considerevole)

A) $ time for i in $(seq 1 10); do grep ciao Inbox; done
real    2m14.596s

ovvero 134 secondi, di media 13,4 dato che abbiamo eseguito 10 volte la stessa 
operazione.

poi mi e' venuto in dubbio: tutto quell'output non rallentera' il processo? 
proviamo a buttarlo via... (e poi che greppiamo a fare? faremo anche una 
prova per mandare il tutto in un nuovo file!)

B) $ time for i in $(seq 1 10); do grep ciao Inbox > /dev/null; done
real    2m1.764s

120 secondi, dunque un miglioramento di 1,4 secondi. Non male.
Ma dobbiamo anche considerare che la parola cercata "ciao" e' molto frequente: 
capita in 7409 righe, che stampano un output di 530346 caratteri.
La differenza sarebbe minore se greppassimo una parola rara o inesistente? 
proviamo! (ma visto che mi sono stufato di aspettare sempre cosi' tanto, 
riduciamo a 5 le prove, che va piu' che bene ;)

C) $ time for i in $(seq 1 5); do grep pastrufazio Inbox ; done
real    0m59.588s

D) $ time for i in $(seq 1 5); do grep pastrufazio Inbox > /dev/null; done
real    0m52.489s

A sorpresa, la differenza rimane, anche se minore: 12 secondi senza 
redirezione (ma di fatto non stampa nulla a video), 10,4 secondi con 
redirezione.

Possiamo comunque notare che i tempi sono COMUNQUE piu' bassi ricercando 
parole piu' rare.

E ora, la domanda iniziale: meglio grep stringa file o cat file|grep 
stringa ??

E) $ time for i in $(seq 1 5); do cat Inbox|grep ciao; done
real    0m57.316s

11,4 secondi di media. 2 secondi sotto il test A!

Si e' parlato anche di usare grep -F... proviamo

F) $ time for i in $(seq 1 5); do grep -F ciao Inbox; done
real    0m53.277s

10,64 secondi di media, decisamente sotto al test A.
Proviamo ora ad abbinare i test E ed F per vedere se possiamo migliorare 
ancora.

G) $ time for i in $(seq 1 5); do cat Inbox|grep -F ciao; done
real    0m49.621s

9,92 secondi. Proviamo ora a redirigere su /dev/null.

H) $ time for i in $(seq 1 5); do cat Inbox|grep -F ciao > /dev/null; done
real    0m46.972s

9,39 secondi di media. E' il miglior risultato che sono riuscito a 
raggiungere, e considerando che sono partito da 13,4, la differenza non e' 
poca (4 secondi su 13.4, quasi il 30%). Peccato che se redirigiamo 
a /dev/null concludiamo ben poco. Proviamo a redirigere in un file per sapere 
se conviene.

H) $ time for i in $(seq 1 5); do cat Inbox|grep -F ciao > prova; done
real    0m49.864s

9,96 secondi, molto simile al test G. Si puo' dire che mandare su file e' piu' 
lento, ma non di molto (quantomeno se il file creato e', come in questo caso, 
di 513K).

Il mio HD non e' molto veloce, penso che ipotizzando un HD veloce e un file da 
1 GB il tempo possa essere inferiore ai 50 secondi (che sarebbero il 
quintuplo del tempo da me impiegato per un file da 200 mega).
> Tipicamente userei grep "parola" nomedelfile o in alternativa
> cat nomedelfile | grep "parola".
> Primo dubbio, secondo voi quale dei due è piu' veloce?
Il secondo :-) (e dire che avrei scommesso sul primo...)
> Secondo dubbio, esistono altri modi per parsare un
> file di tali dimensioni senza aspettare tempi biblici e
> nel mentre andare a prendersi un caffè molto molto lungo???
Tutto sommato i tempi non si sono dimostrati proprio biblici.
Comunque dipende anche a cosa ti serve: se il risultato deve essere passato in 
pasto ad un programma o roba cosi' e' un conto, se invece devi leggerlo a 
mano cambia molto: ad esempio  puoi mettere grep a lavorare buttando l'output 
su un nuovo file da leggere nel frattempo con tail -f e less (o, se usi un 
terminale virtuale, basta impostare abbastanza memoria per le informazioni 
stampate e leggere con calma quello che appare man mano)

> Grazie e un saluto, Andrea.
Grazie a te per le prove che mi hai incentivato a fare!

Ciao
Davide



Reply to: