Myślę, że zaletą jest naprawdę to, że redukujesz ilość wymaganych kopii danych w porównaniu z tradycyjnymi metodami odczytu pliku.
Jeśli aplikacja może korzystać z danych „na miejscu” w pliku mapowanym w pamięci, może wejść bez kopiowania; jeśli używasz wywołania systemowego (np. pread () Linuksa), to zazwyczaj oznacza to, że jądro kopiuje dane z własnych buforów do przestrzeni użytkownika. To dodatkowe kopiowanie nie tylko wymaga czasu, ale zmniejsza efektywność pamięci podręcznych procesora poprzez dostęp do tej dodatkowej kopii danych.
Jeśli dane faktycznie muszą być odczytywane z dysku (jak w przypadku fizycznego wejścia / wyjścia), to system operacyjny nadal musi je odczytać, błąd strony prawdopodobnie nie jest lepszy pod względem wydajności niż wywołanie systemowe, ale jeśli one nie (tj. już w pamięci podręcznej systemu operacyjnego), teoretycznie wydajność powinna być znacznie lepsza.
Z drugiej strony nie ma asynchronicznego interfejsu do plików mapowanych w pamięci - jeśli spróbujesz uzyskać dostęp do strony, która nie jest zamapowana, generuje błąd strony, a następnie sprawia, że wątek czeka na I / O.
Oczywistą wadą plików mapowanych w pamięci jest 32-bitowy system operacyjny - łatwo może zabraknąć przestrzeni adresowej.
Użyłem pliku mapowanego w pamięci, aby zaimplementować funkcję „autouzupełniania”, gdy użytkownik pisze. Mam ponad 1 milion numerów katalogowych produktów przechowywanych w jednym pliku indeksu. Plik zawiera typowe informacje nagłówkowe, ale większość pliku to gigantyczna tablica rekordów o stałym rozmiarze posortowanych według pola klucza.
W czasie wykonywania plik jest mapowany w pamięci, rzutowany na tablicę w
C
stylustruct
a, a my wykonujemy wyszukiwanie binarne, aby znaleźć pasujące numery części zgodnie z typami użytkownika. Tylko kilka stron pamięci pliku jest faktycznie odczytywanych z dysku - niezależnie od tego, które strony zostaną trafione podczas wyszukiwania binarnego.źródło
Pliki mapowane w pamięci mogą być używane do zastępowania dostępu do odczytu / zapisu lub do obsługi współbieżnego udostępniania. Kiedy używasz ich do jednego mechanizmu, otrzymujesz także drugi.
Zamiast szukać, pisać i czytać w pliku, mapujesz go do pamięci i po prostu uzyskujesz dostęp do bitów tam, gdzie się spodziewasz.
Może to być bardzo przydatne iw zależności od interfejsu pamięci wirtualnej może poprawić wydajność. Poprawa wydajności może nastąpić, ponieważ system operacyjny może teraz zarządzać tym byłym „operacją we / wy” wraz z całym innym dostępem do pamięci programowej i może (teoretycznie) wykorzystać algorytmy stronicowania i tak dalej, które już wykorzystuje do obsługi pamięć wirtualna dla pozostałej części programu. Zależy to jednak od jakości podstawowego systemu pamięci wirtualnej. Słyszałem anegdoty, które mówią, że systemy pamięci wirtualnej Solaris i * BSD mogą wykazywać lepszą wydajność niż system VM w systemie Linux - ale nie mam danych empirycznych, które mogłyby to potwierdzić. YMMV.
Współbieżność pojawia się, gdy weźmie się pod uwagę możliwość korzystania przez wiele procesów z tego samego „pliku” w pamięci mapowanej. W modelu odczytu / zapisu, jeśli dwa procesy zapisałyby w tym samym obszarze pliku, można było być prawie pewnym, że jeden z danych procesu dotrze do pliku, nadpisując dane drugiego procesu. Dostaniesz jedną lub drugą - ale nie jakieś dziwne mieszanie się. Muszę przyznać, że nie jestem pewien, czy jest to zachowanie nakazane przez jakikolwiek standard, ale jest to coś, na czym można w zasadzie polegać. (Właściwie to dobre pytanie uzupełniające!)
Dla kontrastu, wyobraź sobie dwa procesy „pisania” na mapie. Robią to, robiąc „magazyny pamięci”, co skutkuje stronicowaniem danych przez system operacyjny na dysk - ostatecznie. Ale w międzyczasie można się spodziewać nakładania się zapisów.
Oto przykład. Powiedzmy, że mam dwa procesy, oba zapisują 8 bajtów z przesunięciem 1024. Proces 1 zapisuje „11111111”, a proces 2 zapisuje „22222222”. Jeśli używają wejścia / wyjścia pliku, możesz sobie wyobrazić, że głęboko w systemie operacyjnym znajduje się bufor pełen 1s i bufor pełny 2s, oba kierowane w to samo miejsce na dysku. Jeden z nich dotrze tam pierwszy, a drugi sekundę. W tym przypadku wygrywa ten drugi. Jeśli jednak używam podejścia opartego na plikach mapowanych w pamięci, proces 1 przejdzie do magazynu pamięci o wielkości 4 bajtów, a następnie do innego magazynu pamięci o wielkości 4 bajtów (załóżmy, że nie jest to maksymalny rozmiar magazynu pamięci). Proces 2 będzie robił to samo. W zależności od tego, kiedy procesy są uruchomione, możesz spodziewać się następujących informacji:
Rozwiązaniem tego problemu jest zastosowanie jawnego wzajemnego wykluczenia - co jest prawdopodobnie dobrym pomysłem w każdym przypadku. W każdym razie polegałeś na systemie operacyjnym, który zrobi „właściwą rzecz” w przypadku odczytu / zapisu pliku we / wy.
Prymitywem klasyfikacji wzajemnego wykluczania jest muteks. W przypadku plików mapowanych w pamięci sugerowałbym przyjrzenie się muteksowi mapowanemu w pamięci, dostępnemu za pomocą (np.) Pthread_mutex_init ().
Edytuj za pomocą jednej gotcha: Kiedy używasz zmapowanych plików, istnieje pokusa, aby osadzić wskaźniki do danych w pliku, w samym pliku (myślę, że połączona lista przechowywana w zmapowanym pliku). Nie chcesz tego robić, ponieważ plik może być mapowany pod różnymi adresami bezwzględnymi w różnym czasie lub w różnych procesach. Zamiast tego użyj przesunięć w mapowanym pliku.
źródło
Problemem byłaby współbieżność. Losowy dostęp jest łatwiejszy Wydajność jest dobra lub świetna. Łatwość użycia. Nie tak dobre. Przenośność - nie tak gorąco.
Użyłem ich w systemie Sun dawno temu i to są moje myśli.
źródło