2013-10-30 30 views
10

To pytanie jest związane z How to use grep efficiently?Jak używać grep z dużymi (mln) liczbę plików, aby wyszukać ciąg i uzyskać wynik w ciągu kilku minut

próbuję wyszukać „string” w folderze, który ma 8-10 milionów małych (~ 2-3kb) plików tekstowych. Muszę znać wszystkie pliki, które mają "ciąg".

Na pierwszy użyłem tego

grep "string" 

który był bardzo powolny.

Potem próbowałem

grep * "string" {} \; -print 

podstawie połączonego pytanie, kiedyś to

find . | xargs -0 -n1 -P8 grep -H "string" 

otrzymuję ten błąd:

xargs: argument line too long 

Czy ktoś zna sposób, aby wykonać to zadanie względnie szybszy?

Uruchamiam to wyszukiwanie na serwerze, który ma więcej niż 50 GB dostępnej pamięci RAM i 14 rdzeni procesora. Chciałbym jakoś wykorzystać całą moc obliczeniową, aby szybciej przeprowadzić to wyszukiwanie.

+0

Czy chcesz wiedzieć, w którym pliku znajduje się ciąg? Czy wystarczy znać ciąg w jednym lub więcej plików w katalogu? –

+0

Potrzebuję znać całą nazwę pliku, w którym znaleziono ciąg. – Watt

Odpowiedz

9

Należy usunąć -0 argument xargs i aż -n parametr zamiast:

... | xargs -n16 ... 
+0

+1 Dzięki! zadziałało. Będę czekać na kilka innych odpowiedzi, zanim zaakceptuję to jako odpowiedź. – Watt

+0

'-n64' lub' -n128' może bardziej realistyczną liczbę. – phs

+0

jest 'n' liczba jednoczesnych procesów? – Watt

0

8 milionów plików to dużo w jednym katalogu! Jednak 8 milionów razy 2 kb to 16 GB, a masz 50 GB pamięci RAM. Mam na myśli ramdysku ...

+0

Tak, jest zbyt wiele plików w folderze. Czy możesz rozwinąć swoje rozwiązanie, jak szybciej wyszukiwać "ciąg"? – Watt

+0

Niestety nie mam jeszcze rozwiązania ... Nadal próbuję zrozumieć parametry pytania. Z jakiego systemu operacyjnego korzystasz? Jakiego systemu plików używasz? Czy próbowałeś samemu uruchomić polecenie "znajdź" i zmierzyć czas? znaleźć czas. | wc -l –

+0

System operacyjny: Ubuntu (najnowsza wersja). Znajdź zwrócony wynik w ciągu 2 sekund – Watt

10

To nie jest tak wielki stos plików (Kudos do 10⁷ plików - messys sen) ale stworzyłem 100k plików (400 MB ogółem) z

for i in {1..100000}; do head -c 10 /dev/urandom > dummy_$i; done 

i kilka testów dla czystej ciekawości (słowo kluczowe szukałem jest wybierana losowo):

> time find . | xargs -n1 -P8 grep -H "10" 
real 0m22.626s 
user 0m0.572s 
sys 0m5.800s 

> time find . | xargs -n8 -P8 grep -H "10" 
real 0m3.195s 
user 0m0.180s 
sys 0m0.748s 

> time grep "10" * 
real 0m0.879s 
user 0m0.512s 
sys 0m0.328s 

> time awk '/10/' * 
real 0m1.123s 
user 0m0.760s 
sys 0m0.348s 

> time sed -n '/10/p' * 
real 0m1.531s 
user 0m0.896s 
sys 0m0.616s 

> time perl -ne 'print if /10/' * 
real 0m1.428s 
user 0m1.004s 
sys 0m0.408s 

Przy okazji. nie ma dużej różnicy w czasie działania, jeśli pomijam wyjście z rurociągiem STDOUT do /dev/null. Używam Ubuntu 12.04 na niezbyt mocnym laptopie;) Mój procesor to Intel (R) Core ™ i3-3110M CPU @ 2.40GHz.

Więcej ciekawość:

> time find . | xargs -n1 -P8 grep -H "10" 1>/dev/null 

real 0m22.590s 
user 0m0.616s 
sys 0m5.876s 

> time find . | xargs -n4 -P8 grep -H "10" 1>/dev/null 

real m5.604s 
user 0m0.196s 
sys 0m1.488s 

> time find . | xargs -n8 -P8 grep -H "10" 1>/dev/null 

real 0m2.939s 
user 0m0.140s 
sys 0m0.784s 

> time find . | xargs -n16 -P8 grep -H "10" 1>/dev/null 

real 0m1.574s 
user 0m0.108s 
sys 0m0.428s 

> time find . | xargs -n32 -P8 grep -H "10" 1>/dev/null 

real 0m0.907s 
user 0m0.084s 
sys 0m0.264s 

> time find . | xargs -n1024 -P8 grep -H "10" 1>/dev/null 

real 0m0.245s 
user 0m0.136s 
sys 0m0.404s 

> time find . | xargs -n100000 -P8 grep -H "10" 1>/dev/null 

real 0m0.224s 
user 0m0.100s 
sys 0m0.520s 
+1

+1 Dla testów porównawczych i ważnych informacji – Watt

-2

Jeśli masz tak dużo RAM, dlaczego nie czytać to wszystko w pamięci i użyć zwykłej biblioteki ekspresyjnej szukać? To prosty program w języku C:

#include <fcntl.h> 
    #include <regex.h> 
    ...