Mam FILE_A, który ma ponad 300 000 linii i FILE_B, który ma ponad 30 milionów linii. Utworzyłem skrypt Bash, który przechwytuje każdą linię w pliku FILE_A w pliku FILE_B i zapisuje wynik polecenia grep w nowym pliku.
Cały ten proces trwa ponad 5 godzin.
Jak mogę poprawić wydajność mojego skryptu?
Używam grep -F -m 1
jako polecenia grep. FILE_A wygląda następująco:
123456789
123455321
a FILE_B wygląda następująco:
123456789,123456789,730025400149993,
123455321,123455321,730025400126097,
Tak więc w Bash mam while
pętlę, która wybiera następną linię w FILE_A i greps w FILE_B. Kiedy wzorzec zostanie znaleziony w PLIKU_B, zapisuję go w pliku wynikowym.txt.
while read -r line; do
grep -F -m1 $line 30MFile
done < 300KFile
algorithms
performance
perl
bash
rogerio_marcio
źródło
źródło
Oto odpowiedź Perla na potomstwo. Rutynowo robię to w celu dopasowania linii 1M do linii 30-35M. Zakończenie zajmuje około 10 sekund.
Najpierw haszuj FILE_A:
Następnie, jeśli twój duży plik jest rozdzielany i wiesz, po której kolumnie chcesz szukać, po prostu sprawdź, czy istnieje klucz skrótu podczas uruchamiania FILE_B, co jest znacznie, dużo szybsze niż sprawdzanie równości lub dopasowania wyrażeń regularnych:
Jeśli większy plik docelowy nie daje się łatwo przeanalizować, skrypt traci swoją wartość, ponieważ duża część jego szybkości wynika z konieczności uruchamiania silnika wyrażeń regularnych .
źródło
Jeśli nie masz nic przeciwko bardziej zaangażowanemu programowaniu, rozważ użycie drzewa sufiksów (lub jego wariantu).
Możesz wstępnie przetwarzać
FILE_B
przy użyciu algorytmu Ukkonen w czasie liniowym. Następnie przeszukujesz każdą linię wFILE_A
czasie liniowo wzdłuż linii i otrzymujesz wszystkie pasujące numery linii (może być konieczne dostosowanie drzewa tad), które możesz zapisać do pliku wynikowego.Cała procedura przebiega w czasie O (n + Nm), jeśli n jest długością
FILE_B
,N
jest liczbą liniiFILE_A
wm, a m jest długością najdłuższej linii wFILE_A
- jest to zasadniczo liniowy czas działania. Pokonuje kwadratowy czas, jakiego potrzebuje twoje oryginalne podejście pod względem wielkości.źródło
--mmap
Ostatnio znalazłem flagę, nie miałem okazji jej przetestować, ale z przyjemnością usłyszę o twoich ustaleniach. Oto opis ze strony man:Zobacz to lub to, aby uzyskać dodatkowe informacje na temat
mmap
.źródło
--mmap
dawki niczego nie zrzucam, zalecałbym bieg z--mmap
, i jeden bez. A potem użyj,wc
aby zobaczyć, że masz taką samą moc wyjściową - to powinien być solidny test, biorąc pod uwagę, że uruchomiliśmy 2 razy grep, a tylko flaga się różniła.dlaczego nie umieścisz tego pliku w bazie danych, bazy danych są naprawdę dobre w wykonywaniu efektywnego łączenia, mieszania, łączenia zagnieżdżonego w ten sposób. I są naprawdę dobrzy w wykorzystaniu pamięci wirtualnej
źródło