To pytanie powtarza się często w StackOverflow, ale przeczytałem wszystkie poprzednie stosowne odpowiedzi i nieznacznie skręciłem pytanie.Wyszukiwanie binarne na dużym pliku dyskowym w języku C - problemy
Mam plik 23 GB zawierający 475 milionów linii o równej wielkości, z każdą linią składającą się z 40-znakowego kodu skrótu, po którym następuje identyfikator (liczba całkowita).
Mam strumień przychodzących kodów skrótu - w sumie miliardów - i dla każdego przychodzącego kodu skrótu muszę go zlokalizować i wydrukować odpowiedni identyfikator. Ta praca, choć duża, musi być wykonana tylko raz.
Plik jest zbyt duży dla mnie do odczytu do pamięci, a więc starali się usemmap w następujący sposób:
codes = (char *) mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,codefile,0);
Potem po prostu zrobić wyszukiwania binarnego za pomocą adresu arytmetyczne na podstawie adresu w kody.
Wydaje się rozpocząć pracę pięknie i produkuje kilka milionów identyfikatorów w ciągu kilku sekund, przy użyciu 100% procesora, ale to po niektórych, pozornie przypadkowe, czas zwalnia do indeksowania. Kiedy patrzę na proces za pomocą ps, zmieniło się ze statusu "R" przy użyciu 100% procesora, na status "D" (diskbound), używając 1% procesora.
Nie można tego powtórzyć - mogę ponownie rozpocząć proces na tych samych danych i może to potrwać 5 sekund lub 10 sekund, zanim nastąpi "powolne indeksowanie". Kiedyś ubiegłej nocy, miałem prawie minutę przed tym, zanim to się stało.
Wszystko jest tylko do odczytu, nie próbuję żadnych zapisów do pliku i zatrzymałem wszystkie inne procesy (które kontroluję) na komputerze. Jest to nowoczesny 64-bitowy komputer Red Hat Enterprise Linux.
Czy ktoś wie, dlaczego proces staje się związany z dyskiem i jak go zatrzymać?
UPDATE:
Dzięki wszystkim za odbieranie i dla swoich pomysłów; Nie próbowałem wcześniej wszystkich różnych ulepszeń, ponieważ zastanawiałem się, czy w jakiś sposób niewłaściwie używam mmap. Ale istotą odpowiedzi wydawało się, że jeśli nie będę w stanie wcisnąć wszystkiego do pamięci, nieuchronnie napotkam problemy. Więc zgniotłem rozmiar kodu skrótu do rozmiaru przedrostka wiodącego, który nie tworzył żadnych duplikatów - wystarczało pierwszych 15 znaków. Następnie wyciągnąłem plik wynikowy do pamięci i uruchomiłem przychodzące kody skrótów w partiach po około 2 miliardy.
Uderzasz w ograniczenia pamięci wirtualnej. Podczas gdy aktywny zestaw danych mieści się w pamięci, wszystko jest hunkydoryczne; gdy zachodzi potrzeba uzyskania dostępu losowego przez zbyt duży zbiór danych, aby zmieścił się on w pamięci, rozpoczniesz twardą stronicowanie, stając się dyskiem. Nie ma łatwego sposobu obejścia tego. Czy liczba całkowita jest przechowywana jako 4-bajtowa lub 8-bajtowa wartość binarna lub jako ciąg znaków? Czy restrukturyzacja pliku 23 GiB jest możliwa? –
@paxdiablo: Problem nie ogranicza rozmiaru pamięci wirtualnej; problemem jest podstawowa pamięć fizyczna. Program wciąż działa, ale losowy dostęp do ponad 23 GiB danych, gdy pamięć fizyczna wynosi, powiedzmy 16 GiB, oznacza, że gdy masz 2/3 pliku w pamięci, to po średnio musisz przeczytaj nową stronę dla jednego dostępu do pamięci w trzech, co jest boleśnie powolne. –
@ JonathanLeffler: Tak, zdałem sobie sprawę, co miałeś na myśli po ponownym przeczytaniu (stąd mój komentarz usunięty). To, co mnie rzuciło, to twierdzenie, że było to ograniczenie pamięci wirtualnej (czytałem to jako wielkość), a nie pamięć wirtualna _management_ (tj. Mapowanie, jak wyjaśniłeś w swojej odpowiedzi). – paxdiablo