Chciałbym wiedzieć, czy jest jakaś wskazówka, którą należy zrobić grep
jak najszybciej. Mam dość dużą bazę plików tekstowych do przeszukania w możliwie najszybszy sposób. Zrobiłem je wszystkie małymi literami, aby pozbyć się -i
opcji. To znacznie przyspiesza wyszukiwanie.
Dowiedziałem się też, że tryby -F
i -P
tryby są szybsze niż domyślne. Pierwszego używam, gdy szukany ciąg nie jest wyrażeniem regularnym (tylko zwykłym tekstem), drugiego, jeśli chodzi o wyrażenie regularne.
Czy ktoś ma jakieś doświadczenie w przyspieszaniu grep
? Może skompiluj go od podstaw z jakąś konkretną flagą (jestem na Linux CentOS), uporządkuj pliki w określony sposób, a może w jakiś sposób spraw, by wyszukiwanie było równoległe?
grep
, być może nadszedł czas, aby poszukać rozwiązania, które umożliwi ich prawidłowe indeksowanie („najlepsze” rozwiązanie będzie zależeć od tego, jakiego rodzaju są to pliki)."...or maybe make the search parallel in some way?"
Byłbym naprawdę podekscytowany, gdybym o tym usłyszał.grep
powinien całkowicie działać równolegle, ale podejrzewam, że wyszukiwanie może nadal być ograniczone we / wy.ack-grep
?ack-grep
lub lepiej Ag! geoff.greer.fm/2011/12/27/the-silver-searcher-better-than-ackOdpowiedzi:
Wypróbuj równolegle z GNU , który zawiera przykład, jak go używać z
grep
:W przypadku dużych plików może podzielić dane wejściowe na kilka części za pomocą argumentów
--pipe
i--block
:Możesz również uruchomić go na kilku różnych maszynach przez SSH (ssh-agent potrzebny do uniknięcia haseł):
źródło
--color=always
do zachowania koloru grepa (dotyczy to również sytuacji, gdy używasz grepa w rurze)find
ma-print0
predykat (większość tak), lepiej byłoby go użyćfind . -type f -print0 | parallel -0 -k …
. Mój przykładman(1) parallel
faktycznie to mówi. Podejrzewam też, żeglobstar
możesz to zrobić jeszcze szybciej, jeśli szukasz konkretnego wzoru pliku:shopt -s globstar; parallel -k -j150% -n 1000 -m fgrep -H -n STRING ::: **/*.c
cat
jeśli chceszsudo
uzyskać dostępbigfile
Jeśli szukasz bardzo dużych plików, ustawienie ustawień regionalnych może naprawdę pomóc.
GNU grep działa dużo szybciej w locale C niż w UTF-8.
export LC_ALL=C
źródło
Ripgrep twierdzi, że jest teraz najszybszy.
https://github.com/BurntSushi/ripgrep
Domyślnie obejmuje również równoległość
Z pliku README
źródło
Najwyraźniej użycie --mmap może pomóc w niektórych systemach:
http://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html
źródło
Nie tylko ulepszenie kodu, ale coś, co uznałem za pomocne po uruchomieniu grepa na ponad 2 milionach plików.
Operację przeniosłem na tani dysk SSD (120 GB). Za około 100 USD jest to niedroga opcja, jeśli regularnie przetwarzasz wiele plików.
źródło
Jeśli nie dbasz o to, które pliki zawierają ciąg, możesz chcieć rozdzielić czytanie i grepowanie na dwa zadania, ponieważ
grep
wielokrotne odradzanie się może być kosztowne - raz dla każdego małego pliku.Jeśli masz jeden bardzo duży plik:
parallel -j100% --pipepart --block 100M -a <very large SEEKABLE file> grep <...>
Wiele małych skompresowanych plików (posortowanych według i-węzła)
ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j80% --group "gzcat {}" | parallel -j50% --pipe --round-robin -u -N1000 grep <..>
Zwykle kompresuję pliki za pomocą lz4 dla maksymalnej przepustowości.
Jeśli chcesz tylko nazwę pliku z dopasowaniem:
ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j100% --group "gzcat {} | grep -lq <..> && echo {}
źródło
Opierając się na odpowiedzi Sandro, spojrzałem na odniesienie, które tu podał i bawiłem się z BSD grep kontra GNU grep. Moje szybkie wyniki testów porównawczych pokazały: GNU grep jest o wiele szybszy.
Tak więc moja rekomendacja do pierwotnego pytania „najszybszy możliwy grep”: Upewnij się, że używasz GNU grep zamiast BSD grep (co jest na przykład domyślne w MacOS).
źródło
Osobiście używam ag (srebrnego poszukiwacza) zamiast grepa i jest znacznie szybszy, można go również połączyć z blokiem równoległym i rurowym.
https://github.com/ggreer/the_silver_searcher
Aktualizacja: teraz używam https://github.com/BurntSushi/ripgrep, który jest szybszy niż ag, w zależności od przypadku użycia.
źródło
Jedną rzeczą, którą znalazłem szybciej przy używaniu grep do wyszukiwania (szczególnie do zmiany wzorców) w jednym dużym pliku, jest użycie split + grep + xargs z jego flagą równoległą. Na przykład:
Posiadanie pliku z identyfikatorami, które chcesz wyszukać w dużym pliku o nazwie my_ids.txt Nazwa dużego pliku bigfile.txt
Użyj podziału, aby podzielić plik na części:
# Use split to split the file into x number of files, consider your big file # size and try to stay under 26 split files to keep the filenames # easy from split (xa[a-z]), in my example I have 10 million rows in bigfile split -l 1000000 bigfile.txt # Produces output files named xa[a-t] # Now use split files + xargs to iterate and launch parallel greps with output for id in $(cat my_ids.txt) ; do ls xa* | xargs -n 1 -P 20 grep $id >> matches.txt ; done # Here you can tune your parallel greps with -P, in my case I am being greedy # Also be aware that there's no point in allocating more greps than x files
W moim przypadku to zredukowało pracę trwającą 17 godzin do 1 godziny 20 minut. Jestem pewien, że jest tu jakaś krzywa dzwonkowa dotycząca wydajności i oczywiście przeglądanie dostępnych rdzeni nie przyniesie ci nic dobrego, ale było to znacznie lepsze rozwiązanie niż którykolwiek z powyższych komentarzy dla moich wymagań, jak podano powyżej. Ma to dodatkową zaletę w porównaniu ze skryptem równoległym w używaniu głównie (linuxowych) natywnych narzędzi.
źródło
cgrep, jeśli jest dostępny, może być o rząd wielkości szybszy niż grep.
źródło
MCE 1.508 zawiera skrypt opakowujący {plik, lista} na poziomie podwójnych porcji, obsługujący wiele plików binarnych C. agrep, grep, egrep, fgrep i tre-agrep.
https://metacpan.org/source/MARIOROY/MCE-1.509/bin/mce_grep
https://metacpan.org/release/MCE
Nie trzeba konwertować na małe litery, jeśli chcemy, aby -i działało szybko. Po prostu przekaż --lang = C do mce_grep.
Kolejność wyników jest zachowywana. Wyjście -n i -b jest również poprawne. Niestety tak nie jest w przypadku równoległego GNU wspomnianego na tej stronie. Naprawdę liczyłem na to, że GNU Parallel będzie tutaj działać. Ponadto mce_grep nie podpowłoce (SH -c / ścieżka / do / grep) przy wywołaniu binarny.
Inną alternatywą jest moduł MCE :: Grep dołączony do MCE.
źródło
Niewielkie odchylenie od pierwotnego tematu: narzędzia wiersza poleceń wyszukiwania indeksowanego z projektu googlecodesearch są znacznie szybsze niż grep: https://github.com/google/codesearch :
Po skompilowaniu ( plik golang potrzebny jest pakiet ), możesz zindeksować folder za pomocą:
# index current folder cindex .
Indeks zostanie utworzony w ramach
~/.csearchindex
Teraz możesz wyszukiwać:
# search folders previously indexed with cindex csearch eggs
Nadal przepuszczam wyniki przez grep, aby uzyskać kolorowe dopasowania.
źródło