W przypadku naprawdę dużego pliku, takiego jak 1 GB, wc -l
dzieje się to powoli. Czy mamy szybszy sposób obliczania liczby nowych linii dla określonego pliku?
command-line
wc
prosti
źródło
źródło
0x0A
inessacji, we / wy jest niewątpliwie wąskim gardłem.wc
masz zbyt dużo kosztów ogólnych, możesz spróbować wdrożyć własneforeach byte in file: if byte == '\n': linecount++
. Jeśli zaimplementowane w C lub asemblerze, nie sądzę, że przyspieszy, chyba że w przestrzeni jądra na RTOS o najwyższym priorytecie (lub nawet w tym celu użyj przerwania - po prostu nie możesz nic zrobić z systemem. .. w porządku, dygresję ;-))time wc -l some_movie.avi
niebuforowanego pliku, w wyniku czego5172672 some_movie.avi -- real 0m57.768s -- user 0m0.255s -- sys 0m0.863s
. Co w zasadzie dowodzi, że @thrig ma rację, we / wy zaburza wydajność w tym przypadku.time wc -l some_large_file_smaller_than_cache
dwa razy z rzędu szybko i zobacz, jak szybka jest druga operacja, a następnietime wc -l some_large_file_larger_than_cache
zobacz, jak czas nie zmienia się między uruchomieniami. W przypadku pliku o wielkości ~ 280 MB czas ten wynosi od 1,7 sekundy do 0,2 sekundy, ale w przypadku pliku 2 GB jest to 14 sekund za każdym razem./usr/bin/time wc -l <file>
mówi? Jaki masz sprzęt? Czy to szybciej, jeśli uruchomisz polecenie wielokrotnie? Naprawdę potrzebujemy więcej informacji;)Odpowiedzi:
Możesz spróbować napisać w C:
Zapisz np.,
wcl.c
Skompiluj np. Zgcc wcl.c -O2 -o wcl
i uruchom zTo powoduje, że nowe linie są posypane plikiem 1 GB w moim systemie w około 370 ms (powtarzane przebiegi). (Zwiększenie rozmiarów buforów nieznacznie wydłuża czas, którego należy się spodziewać - BUFSIZ powinien być bliski optymalnego). Jest to bardzo porównywalne do ~ 380 ms, z którego otrzymuję
wc -l
.Mmaping daje mi lepszy czas około 280 ms , ale oczywiście ma ograniczenie polegające na ograniczeniu się do rzeczywistych plików (bez FIFOS, bez wejścia na terminal itp.):
Plik testowy utworzyłem za pomocą:
i dodał kilka nowych linii testowych z:
i edytor szesnastkowy.
źródło
for
pętli OpenMP ) może przynieść pewne korzyści, dzięki czemu można poczynić pewne postępy, gdy jeden wątek jest zablokowany w oczekiwaniu na dane wejściowe. Ale z drugiej strony może to utrudniać planowanie operacji we / wy, więc wszystko, co mogę polecić, to wypróbować i zmierzyć!read()
Wersja może korzystać z odczytu z wyprzedzeniem.Możesz ulepszyć rozwiązanie sugerowane przez @pskocik, zmniejszając liczbę połączeń z
read
. Istnieje wiele wywołań do odczytuBUFSIZ
fragmentów z pliku 1 Gb. Zwykłym podejściem do tego jest zwiększenie rozmiaru bufora:BUFSIZ
jest 8192. W przypadku oryginalnego programu jest to 120 tysięcy operacji odczytu. Prawdopodobnie możesz sobie pozwolić na bufor wejściowy 1 Mb, aby zmniejszyć to o współczynnik 100.Podczas porównywania różnych podejść możesz mieć na uwadze, że niektóre systemy (takie jak Linux) wykorzystują większość nieużywanej pamięci komputera jako pamięć podręczną dysku. Jakiś czas temu (prawie 20 lat temu, wspomniane w nikczemnym FAQ ), byłem zaskoczony nieoczekiwanie dobrymi wynikami z (niezbyt dobrego) algorytmu stronicowania, który opracowałem do obsługi warunków niskiej pamięci w edytorze tekstu. Wyjaśniono mi, że działał szybko, ponieważ program działał z buforów pamięci używanych do odczytu pliku, i że tylko jeśli plik zostanie ponownie odczytany lub zapisany, będzie różnica prędkości.
To samo dotyczy
mmap
(w innym przypadku, który wciąż znajduje się na mojej liście rzeczy do zrobienia w celu włączenia do FAQ, deweloper zgłosił bardzo dobre wyniki w scenariuszu, w którym pamięć podręczna dysku była faktycznym powodem poprawy). Opracowanie testów porównawczych wymaga czasu i staranności, aby przeanalizować przyczyny dobrej (lub złej) wydajności.Dalsza lektura:
źródło
dd
użyciem buforów 1 MB jest wolniejsze niż 8 KB. Domyślna wartość 8KB dla wc jest właściwie wybrana całkiem dobrze, będzie bliska optymalnej dla szerokiego zakresu systemów.