Wymuś, aby katalog zawsze był w pamięci podręcznej

35

Testowałem różne metody, aby skrócić czas kompilacji całego mojego projektu w C ++. Obecnie zajmuje to około 5 minut. Eksperymentowałem z distcc, ccache i innymi. Niedawno odkryłem, że jeśli skopiuję cały projekt na dysk RAM, a następnie skompiluję stamtąd, skróci to czas kompilacji do 30% jego oryginalnego - zaledwie 1,5 minuty.

Oczywiście praca z napędu RAM nie jest praktyczna. Czy ktoś wie, w jaki sposób mogę zmusić system operacyjny do przechowywania określonego katalogu w pamięci podręcznej ? Nadal chcę, aby katalog został zsynchronizowany z powrotem na dysk, jak zwykle, ale zawsze chcę również kopię danych w pamięci. czy to możliwe?

EDYCJA: Jako możliwe rozwiązanie, właśnie pomyśleliśmy o uruchomieniu demona, który działa rsyncco około 10 sekund, aby zsynchronizować dysk z dyskiem RAM. Następnie uruchamiamy kompilację z napędu RAM. rsyncJest niezwykle szybkie, ale czy to naprawdę działa? Z pewnością system operacyjny mógłby zrobić lepiej ...

JaredC
źródło
Pamięć podręczna nie jest jedyną różnicą między tmpfs a ext3 / 4; mają na przykład dzienniki, które będą pisane bez względu na buforowanie.
André Paramés
1
Czy możesz timepodać swoją kompilację i podzielić się z nami wynikiem? Rozwiałoby to pewne kontrowersje. make clean && /usr/bin/time -v make(nie używaj wbudowanego timepolecenia bash )
shellholic
1
@she Dlaczego nie wbudowane polecenie bash?
tshepang
3
@Tshepang timewbudowany bash ( help time) ma o wiele mniej szczegółów (brak opcji pełnych ) niż czas GNU ( man time) dotyczący I / O, przełączników kontekstu, ...
shellholic

Odpowiedzi:

18

Oczywistym sposobem przechowywania wielu plików w pamięci podręcznej jest częsty dostęp do nich. Linux jest całkiem dobry w arbitrażu między zamianą a buforowaniem, więc podejrzewam, że zaobserwowana różnica prędkości nie wynika z tego, że system operacyjny nie przechowuje danych w pamięci podręcznej, ale z innej różnicy między użyciem tmpfs a innymi próbami.

Spróbuj obserwować, co robi IO w każdym przypadku. Podstawowym narzędziem do tego jest iotop. Przydatne mogą być inne narzędzia; zobacz rozkład obciążenia IO dysku Linux, według ścieżki systemu i / lub procesu? , Jaki program w systemie Linux może mierzyć we / wy w czasie? i inne wątki związane z awarią serwera.

Oto kilka hipotez dotyczących tego, co może się dziać. Jeśli wykonasz pomiary, pokaż je, abyśmy mogli potwierdzić lub obalić te hipotezy.

  • Jeśli masz włączone czasy dostępu do plików , system operacyjny może tracić sporo czasu na pisanie tych czasów dostępu. Czasy dostępu są bezużyteczne dla drzewa kompilacji, więc upewnij się, że są wyłączone z noatimeopcją montowania. Twoje rozwiązanie tmpfs + rsync nigdy nie czyta z dysku twardego, więc nigdy nie musi poświęcać dodatkowego czasu na pisanie.
  • Jeśli zapisy są synchronizowane , albo dlatego, że kompilator wywołuje, sync()albo dlatego, że jądro często opróżnia bufory wyjściowe, zapisy potrwają dłużej na dysk twardy niż w tmpfs.
Gilles „SO- przestań być zły”
źródło
Też mam to uczucie. Kompilacja wymaga intensywnego procesora, a nie operacji we / wy.
phunehehe,
Hmmm, chciałbym zobaczyć tutaj komentarz @JaredC potwierdzający lub odrzucający hipotezę Gillesa. Różnica między 1,5 a 5 minut jest sporą różnicą ...
Daniel Alder
8

Linux domyślnie używa pamięci RAM jako pamięci podręcznej dysku. Jako demonstrację spróbuj uruchomić time find /some/dir/containing/a/lot/of/files > /dev/nulldwa razy, drugi raz jest znacznie szybszy, ponieważ wszystkie i-węzły dyskowe są buforowane. Chodzi o to, jak wykorzystać tę funkcję jądra i zatrzymać próbę jej zastąpienia.

Chodzi o zmianę swappiness. Rozważmy trzy główne typy wykorzystania pamięci: aktywne programy, nieaktywne programy i pamięć podręczna dysku. Oczywiście pamięci używanej przez aktywne programy nie należy zamieniać, a wybór między dwoma innymi jest dość arbitralny. Czy chcesz szybkie przełączanie programów lub szybki dostęp do plików? Niski swappiness woli zachować w pamięci programów (nawet jeśli nie jest używany przez dłuższy czas) i wysokiej swappiness woli zachować więcej pamięci podręcznej dysku (poprzez zamianę nieużywane programy). (skala zamiany wynosi od 0 do 100, a wartość domyślna to 60)

Moim rozwiązaniem twojego problemu jest zmiana swapiness na bardzo wysoki (90-95, żeby nie powiedzieć 100) i załadowanie pamięci podręcznej:

echo 95 | sudo tee /proc/sys/vm/swappiness > /dev/null # once after reboot
find /your/source/directory -type f -exec cat {} \; > /dev/null

Jak się domyślacie, trzeba mieć wystarczającą ilość wolnej pamięci, aby pomieścić w pamięci podręcznej wszystkie pliki źródłowe i pliki obiektów, a także kompilator, dołączone pliki nagłówków, połączone biblioteki, IDE i inne używane programy.

shellholic
źródło
Jest to ogólnie przydatne, ale tak naprawdę chcę, aby mój kod źródłowy miał niską wymienność, ale wszystko inne - normalną zamianę. Zasadniczo, mam wiele rzeczy dzieje się w tle, ale chcę, aby ograniczyć je do 6 z 8 GBs, natomiast zawsze zachowując pozostałe 2 GB do kodu źródłowego. Nie chcę ryzykować, że zostanie zamieniony ... kiedykolwiek ... bo to denerwujące.
JaredC
Swappiness ma charakter systemowy. W rzeczywistości, jeśli robisz coś innego, a twoje pliki są rozładowywane z pamięci, musisz tylko załadować to z drugą linią. Jeśli pamięć musi zostać uwolniona dla czegoś innego, tak naprawdę nie „chcesz zaryzykować”, aby zrobić to z zamiany. BTW, tmpfsw tym samym przypadku również zostałby wymieniony.
shellholic
2
Osobiście spadłem wysoka zamiana jest strasznie okropna na stacjach roboczych. Chociaż niektóre funkcje mogą zostać przyspieszone przez większą pamięć podręczną (tj. Więcej buforowanych plików) ma to swoją cenę: płacisz za to pod względem szybkości reakcji podczas przełączania programów, co użytkownicy zauważają najpierw podczas pracy w systemie. Przechodząc z przeglądarki do biura na inną przeglądarkę na e-mail, po prostu nie mogę znieść oczekiwania na 1-2 sekundy, aż każdy program ponownie wróci. Na wszystkich moich komputerach z linuksem generalnie ustawiam swappiness na niską wartość 10.
fgysin przywraca Monikę
6

Wymuszanie buforowania nie jest właściwym sposobem na zrobienie tego. Lepiej przechowywać źródła na dysku twardym i kompilować je na tmpfs. Wiele systemów kompilacji, takich jak qmake i CMake, obsługuje kompilacje poza źródłami.

gelraen
źródło
6

Te inosyncdźwięki demon jak to robi dokładnie to, co chcesz, jeśli masz zamiar rsync do ramdysku. Zamiast rsynchronizować co około 10 sekund, używa funkcji inotify Linuksa do rsyncowania, gdy plik się zmienia. Znalazłem go w repozytorium Debiana jako inosyncpakiet lub jego źródło jest dostępne pod adresem http://bb.xnull.de/projects/inosync/ .

Jander
źródło
Brzmi całkiem użytecznie. Zajrzę do tego i zdam raport. Dzięki!
JaredC
5

Wydaje mi się, że to działa, jeśli chcę przechowywać niektóre pliki lub wszystkie pliki w określonym katalogu w pamięci podręcznej.

vmtouch wydaje się robić właśnie to. Przykład 5 może być tym, czego potrzebujesz.

vmtouch -dl /whatever/directory/

Musiałem uruchomić go jako root sudo

Highstaker
źródło
1
Nie widzi nowych / usuniętych plików.
Vi.
3

Biorąc pod uwagę wystarczającą pamięć, twoja kompilacja z ramdysku nie wykonuje operacji we / wy. Może to przyspieszyć wszystko, co czyta lub zapisuje pliki. I / O jest jedną z najwolniejszych operacji. Nawet jeśli wszystko zostanie zapisane w pamięci podręcznej przed kompilacją, nadal masz wejścia / wyjścia do zapisu, chociaż powinny one mieć minimalny wpływ.

Możesz przyspieszyć, wstępnie ładując wszystkie pliki do pamięci podręcznej, ale czas potrzebny na to powinien zostać uwzględniony w całkowitych czasach kompilacji. To może nie dać ci dużej przewagi.

Budowanie obiektów i plików pośrednich w pamięci RAM, a nie na dysku. Robienie przyrostowych kompilacji może przynieść znaczące korzyści przy częstych kompilacjach. W większości projektów wykonuję codzienną czystą kompilację i przyrostowe kompilacje pomiędzy nimi. Kompilacje integracyjne są zawsze kompilacjami czystymi, ale staram się ograniczać je do mniej niż jednej dziennie.

Możesz zwiększyć wydajność, używając partycji ext2 z wyłączonym atime. Twoje źródło powinno mieć kontrolę wersji w kronikowanym systemie plików, takim jak ext3 / 4.

BillThor
źródło
2

Jak wspomniano wcześniej, oczywistym sposobem jest odczytanie całej struktury katalogów i zawartości plików, które chcesz buforować.

Możesz to zautomatyzować, pisząc skrypt do monitorowania wyników vmstat 1(użyj dowolnego równoważnego narzędzia dla swojego systemu operacyjnego) i zachowaj sumę liczby zapisanych i odczytanych bloków. Gdy suma przekroczy określony próg, przeczytaj wszystkie pliki, które chcesz buforować, zresetuj sumę, a następnie kontynuuj monitorowanie wyjścia vmstat. Aby szybko odczytywać pliki: jeśli twoje drzewo zawiera wiele plików, unikaj find ... -exec catzamiast tego wypróbuj find ... -print0 | xargs -0 catniestandardowy program, który nie uruchomi cat dla każdego pliku.

Monitorowanie We / Wy dysku jest lepsze niż stosowanie ustalonego interwału, ponieważ sygnalizuje, że dane należy czytać częściej lub rzadziej, w zależności od obciążenia We / Wy dysku.

Z powodzeniem korzystałem z tej zautomatyzowanej metody w systemach, w których zawsze potrzebowałem szybkiego odczytu plików indeksu, unikając operacji we / wy dysku twardego. Użyłem również strace do stworzenia listy każdego pliku, do którego uzyskuje się dostęp po zalogowaniu, dzięki czemu mogę utrzymać wszystko w pamięci podręcznej, aby umożliwić szybkie logowanie.

To może nie być najlepsze możliwe rozwiązanie, ale dobrze mi pasowało.

filebarn
źródło