Kiedy powinienem używać /dev/shm/, a kiedy /tmp/?
Kiedy powinienem używać /dev/shm/
, a kiedy /tmp/
? Czy mogę zawsze polegać na tym, że oba są tam na Unicie?
Kiedy powinienem używać /dev/shm/
, a kiedy /tmp/
? Czy mogę zawsze polegać na tym, że oba są tam na Unicie?
W kolejności malejącej tmpfs
prawdopodobieństwa:
┌───────────┬──────────────┬────────────────┐
│ /dev/shm │ always tmpfs │ Linux specific │
├───────────┼──────────────┼────────────────┤
│ /tmp │ can be tmpfs │ FHS 1.0 │
├───────────┼──────────────┼────────────────┤
│ /var/tmp │ never tmpfs │ FHS 1.0 │
└───────────┴──────────────┴────────────────┘
Ponieważ pytasz o specyficzny dla Linuksa punkt montowania tmpfs versus przenośnie zdefiniowany katalog, który może być tmpfs (w zależności od twojego sysadmina i tego, co jest domyślne dla twojego distro), twoje pytanie ma dwa aspekty, które inne odpowiedzi podkreśliły inaczej:
Konserwatywne wydanie (mieszanka konwencji z FHS i powszechnego użycia):
/tmp
. /var/tmp
dla dużych danych, które mogą nie zmieścić się łatwo w ramie. /var/tmp
dla danych, które warto zachować po ponownym uruchomieniu komputera (jak pamięć podręczna). /dev/shm
jako efekt uboczny wywołania shm_open()
. Zamierzonym odbiorcą są ograniczone bufory, które są bez końca nadpisywane. Więc to jest dla długo żyjących plików, których zawartość jest niestabilna i nie jest strasznie duża. mktemp
respektuje zmienną środowiskową TMPDIR
. Pragmatyczna edycja:
Użyj /dev/shm
, gdy ważne jest, aby używać tmpfs, /var/tmp
, gdy ważne jest, aby nie używać, w przeciwnym razie /tmp
.
fsync
jest no-op na tmpfs. Ten syscall jest wrogiem numer jeden wydajności (IO) (i długowieczności flasha, jeśli o to dbasz), ale jeśli zauważysz, że używasz tmpfs (lub eatmydata ) tylko po to by pokonać fsync, to ty (lub inny programista w łańcuchu) robisz coś źle. Oznacza to, że transakcje w kierunku urządzenia magazynującego są niepotrzebnie drobnoziarniste dla twojego celu - najwyraźniej jesteś skłonny pominąć niektóre punkty zapisu dla wydajności, ponieważ teraz poszedłeś do skrajności sabotowania ich wszystkich - rzadko jest to najlepszy kompromis. Ponadto, to właśnie tutaj, w krainie wydajności transakcji, znajdują się niektóre z największych korzyści z posiadania dysku SSD - każdy przyzwoity dysk SSD będzie osiągał niewiarygodną wydajność w porównaniu z tym, co może wytrzymać dysk wirujący (7200 obr./min = 120 Hz, jeśli nic innego nie uzyskuje dostępu), nie wspominając o kartach pamięci flash, które różnią się znacznie pod względem tej metryki (nie tylko dlatego, że jest to kompromis z wydajnością sekwencyjną, która jest tym, co jest oceniane, np. ocena klasy karty SD). Więc uważajcie, deweloperzy z płonącymi szybkimi dyskami SSD, aby nie zmuszać swoich użytkowników do tego przypadku użycia!
Chcesz usłyszeć śmieszną historię? Moja pierwsza lekcja fsync
: Miałem pracę, która polegała na rutynowym “uaktualnianiu” kilku baz danych Sqlite (przechowywanych jako przypadki testowe) do ciągle zmieniającego się aktualnego formatu. Framework “upgrade” uruchamiał kilka skryptów, wykonując co najmniej jedną transakcję każdy, aby zaktualizować jedną bazę danych. Oczywiście, aktualizowałem moje bazy danych równolegle (8 równolegle, ponieważ zostałem obdarzony potężnym 8-rdzeniowym procesorem). Ale jak się dowiedziałem, nie było żadnego przyspieszenia paralelizacji (raczej niewielki hit), ponieważ proces był całkowicie związany z IO. Przezabawnie, zawijanie frameworka aktualizacji w skrypt, który kopiował każdą bazę danych do /dev/shm
, aktualizował ją tam i kopiował z powrotem na dysk było jak 100 razy szybsze (wciąż z 8 równolegle). Jako bonus, komputer był użyteczny także podczas aktualizacji baz danych.
Odpowiednim użyciem tmpfs jest unikanie niepotrzebnego zapisywania lotnych danych. Efektywnie wyłącza writeback, tak jak ustawienie /proc/sys/vm/dirty_writeback_centisecs
na nieskończoność w zwykłym systemie plików.
Ma to bardzo mało wspólnego z wydajnością, a ominięcie tego jest znacznie mniejszym problemem niż nadużywanie fsync: Czas writeback określa jak leniwie zawartość dysku jest aktualizowana po zawartości pagecache, a domyślne 5 sekund to długi czas dla komputera - aplikacja może nadpisywać plik tak często jak chce, w pagecache, ale zawartość na dysku jest aktualizowana tylko raz na 5 sekund. Chyba, że aplikacja wymusi to za pomocą fsync, czyli. Zastanów się ile razy aplikacja może w tym czasie wypisać mały plik, a zobaczysz dlaczego fsyncowanie każdego z nich byłoby znacznie większym problemem.
fsync
, oczywiście. Przechowywanie zimnych danych. Można by się pokusić o myślenie, że serwowanie plików ze swapu jest tak samo wydajne jak normalny system plików, ale jest kilka powodów dlaczego tak nie jest:
Ok, oto rzeczywistość.
Zarówno tmpfs jak i normalny system plików są cache'owaniem pamięci na dysku.
Tmpfs używa pamięci i swapspace jako swojego backing store, system plików używa określonego obszaru na dysku, żaden z nich nie jest ograniczony rozmiarem systemu plików, jest całkiem możliwe posiadanie 200GB tmpfs na maszynie z mniej niż GB ramu, jeśli masz wystarczająco dużo swapspace.
Różnica polega na tym, kiedy dane są zapisywane na dysku. W przypadku tmpfs dane są zapisywane TYLKO wtedy, gdy pamięć jest zbyt pełna lub gdy jest mało prawdopodobne, że dane zostaną wkrótce użyte. OTOH większość normalnych linuksowych systemów plików jest zaprojektowana tak, aby zawsze mieć mniej więcej stały zestaw danych na dysku, więc jeśli użytkownik wyciągnie wtyczkę, nie straci wszystkiego.
Osobiście, jestem przyzwyczajony do posiadania systemów operacyjnych, które nie ulegają awarii i systemów UPS (np. baterie w laptopach), więc myślę, że systemy plików ext2/3 są zbyt paranoidalne z ich 5-10 sekundowym interwałem punktów kontrolnych. System plików ext4 jest lepszy z 10 minutowym punktem kontrolnym, ale traktuje dane użytkownika jako drugą klasę i nie chroni ich. (ext3 jest taki sam, ale nie zauważasz tego z powodu 5 sekundowego punktu kontrolnego)
To częste checkpointowanie oznacza, że niepotrzebne dane są ciągle zapisywane na dysk, nawet dla /tmp.
W rezultacie musisz utworzyć przestrzeń wymiany tak dużą, jak potrzebny jest /tmp (nawet jeśli musisz utworzyć plik wymiany) i użyć tej przestrzeni do zamontowania tmpfs o wymaganym rozmiarze na /tmp.
NIGDY nie używaj /dev/shm.
Chyba, że używasz go do bardzo małych (prawdopodobnie mmapowanych) plików IPC i jesteś pewien, że on istnieje (nie jest standardem), a maszyna ma więcej niż wystarczającą ilość pamięci + swap.
Użyj /tmp/ dla plików tymczasowych. Użyj /dev/shm/, gdy chcesz współdzielonej pamięci (np. komunikacja międzyprocesowa przez pliki).
Możesz polegać na obecności /tmp/, ale /dev/shm/ jest stosunkowo nową rzeczą tylko dla Linuksa.
Innym przypadkiem, kiedy powinieneś użyć /dev/shm (dla Linuksa 2.6 i wyżej) jest sytuacja, kiedy potrzebujesz gwarantowanego systemu plików tmpfs, ponieważ nie wiesz, czy możesz zapisywać na dysku.
System monitorowania, który znam, musi zapisywać pliki tymczasowe podczas tworzenia raportu do przesłania na centralny serwer. W praktyce o wiele bardziej prawdopodobne jest, że coś uniemożliwi zapis na system plików (albo zabraknie miejsca na dysku, albo awaria RAID zepchnie system w sprzętowy tryb tylko do odczytu), ale nadal będziesz w stanie prześlizgnąć się i zaalarmować o tym, niż jeśli coś spiralę całą dostępną pamięć tak, że tmpfs będzie bezużyteczny (a pudełko nie będzie martwe). W przypadkach takich jak ten, system monitorujący będzie preferował zapis do RAMu, aby potencjalnie móc wysłać alert o pełnym dysku lub martwym/dyndającym sprzęcie.
/dev/shm jest używany dla współdzielonej pamięci wirtualnej specyficznej dla systemu sterowników urządzeń i programów.
Jeśli tworzysz program, który wymaga wirtualnej sterty pamięci, która powinna być zmapowana do pamięci wirtualnej. To idzie podwójnie, jeśli potrzebujesz wielu procesów lub wątków, aby móc bezpiecznie uzyskać dostęp do tej pamięci.
Faktem jest, że tylko dlatego, że sterownik używa specjalnej wersji tmpfs dla niego, nie oznacza, że powinieneś używać go jako ogólnej partycji tmpfs. Zamiast tego, powinieneś po prostu stworzyć inną partycję tmpfs, jeśli chcesz mieć jedną dla swojego katalogu tymczasowego.
W PERLu, mając minimum 8GB na dowolnej maszynie (wszystkie działają pod Linux Mint), mam, jak sądzę, dobry nawyk robienia DB_File-based (struktura danych w pliku) złożonych algorytmów z milionami odczytów i zapisów przy użyciu /dev/shm
W innych językach, nie mając wszędzie gigether, aby uniknąć startów i zatrzymań w transferze sieciowym (pracując lokalnie na pliku, który znajduje się na serwerze w atmosferze klient-serwer), używając pliku wsadowego jakiegoś typu, skopiuję cały (300-900MB) plik naraz na /dev/shm, uruchomię program z wyjściem na /dev/shm, zapiszę wyniki z powrotem na serwer i usunę z /dev/shm
Naturalnie, gdybym miał mniej RAM-u, nie robiłbym tego. Normalnie, system plików w pamięci /dev/shm jest odczytywany jako rozmiar równy połowie dostępnej pamięci RAM. Jednakże, zwykłe użycie pamięci RAM jest stałe. Więc naprawdę nie mógłbyś tego zrobić na urządzeniu z 2GB lub mniej. Aby przekształcić parafrazę w hiperbolę, w pamięci RAM często znajdują się rzeczy, o których nawet system nie informuje dobrze.