Jak działa ładowanie pamięci / zatwierdzenia w systemie Windows 10?

4

Pytanie to wynika z następujących regularnie obserwowanych zjawisk, dla których chciałbym znaleźć wyjaśnienie:

  1. Bieżące zatwierdzanie jest regularnie wyższe niż użycie fizyczne + rozmiar pliku strony. O co chodzi? Czy nie powinno to być niemożliwe? [Wydaje się, że może to być spowodowane kompresją. Co zmienia pytanie: Dlaczego limit nie zatwierdza, a nie idzie w górę czy coś takiego? Jaki jest sens kompresji, jeśli nie pomaga w zużyciu pamięci?]
  2. Czasami osiąga to ekstremalne poziomy, w których Bieżące zatwierdzanie to więcej niż dwukrotne użycie pamięci fizycznej!
  3. Kiedy ładowanie się ładuje i Windows zaczyna prosić mnie o zamknięcie rzeczy, przez większość czasu pamięć fizyczna wynosi około 60%. To wydaje się okropnie nieefektywne.

Dotyczy to systemu Windows 10, jak zgłosił Process Explorer.

Ostateczne pytanie, na które chciałbym odpowiedzieć, brzmi: czy mogę zrezygnować z sztucznego pompowania pliku strony do poziomów, w których mój głodny SSD jest źle wyposażony do obsługi, aby właściwie móc efektywnie wykorzystać moją pamięć fizyczną? (Lub nawet jeśli nie byłby tak pełny. To znaczy, chciałbym unikać sugestii typu „Do X / Y / Z do pliku strony”.)

martixy
źródło
Opłata za zatwierdzenie nie ma nic wspólnego z użyciem pamięci RAM, użyciem pliku strony lub jakiejkolwiek ich kombinacji. Zasadniczo jest to całkowita potencjalna wymagana przestrzeń dyskowa, która może znajdować się w pamięci RAM lub w pliku stronicowania. Limit zatwierdzeń to rozmiar pamięci RAM + rozmiar pliku strony - niewielki narzut. Zatem jedynym sposobem na zwiększenie limitu zatwierdzeń jest zwiększenie rozmiaru pliku strony lub dodanie pamięci RAM. Zwykle ten pierwszy jest najłatwiejszy.
LMiller7
Powiedziałeś już tyle, ale powiedziałeś, że nie masz czasu na dalsze rozwijanie. Właśnie dlatego postanowiłem zapytać tutaj. W moim rozumieniu, opłata zatwierdzenia jest „czymś, w pewnym momencie poprosiła o tyle pamięci, a system operacyjny powiedział, że zrobiono”, a opłata zatwierdzenia odzwierciedla to, czy pamięć jest używana, czy nie. Jednak to nie odpowiada na większość moich pytań. Przynajmniej chciałbym uzyskać odpowiedź na ostatnie pytanie i idealnie chciałbym uzyskać głębszy i bardziej przejrzysty obraz działania zarządzania pamięcią w systemie Windows.
martixy

Odpowiedzi:

8

Jest to właściwie dość proste, gdy zrozumiesz, że opłata zatwierdzenia stanowi tylko potencjalne - ale „gwarantowane dostępne, jeśli chcesz” - wykorzystanie pamięci wirtualnej, podczas gdy „prywatny zestaw roboczy” - który jest zasadniczo pamięcią RAM używaną przez „zatwierdzoną” pamięć - jest faktycznym zastosowaniem, podobnie jak przestrzeń pliku strony. (Ale to nie wszystko z wykorzystania pamięci RAM, ponieważ istnieją inne rzeczy, które używają pamięci RAM).

Załóżmy, że mówimy o systemach 32-bitowych, więc maksymalna wirtualna przestrzeń adresowa dostępna dla każdego procesu wynosi zwykle 2 GiB. (W systemach 64-bitowych nie ma istotnej różnicy w żadnym z poniższych elementów, z tym wyjątkiem, że adresy i rozmiary mogą być większe - znacznie większe).

Załóżmy teraz, że program działający w procesie używa VirtualAlloc (Win32 API) do „zatwierdzenia” 2 MiB pamięci wirtualnej. Jak można się spodziewać, pojawi się to jako dodatkowe 2 MB opłaty zatwierdzenia, a w procesie jest dostępnych o 2 MB mniej bajtów wirtualnej przestrzeni adresowej dla przyszłych przydziałów.

Ale tak naprawdę nie zużyje jeszcze żadnej pamięci fizycznej (RAM)!

Połączenie VirtualAlloc zwróci dzwoniącemu adres początkowy przydzielonego regionu; region będzie gdzieś w zakresie od 0x10000 do 0x7FFEFFFF, tj. około 2 GiB. (Pierwszy i ostatni 64 kB lub 0x10000 szesnastkowy vas w każdym procesie nigdy nie są przypisywane).

Ale znowu - nie ma jeszcze fizycznego wykorzystania 2 MiB pamięci ! Nie w pamięci RAM, nawet w pliku stronicowania. (Istnieje niewielka struktura zwana „deskryptorem adresu wirtualnego”, która opisuje początkową wartość va i długość prywatnego zatwierdzonego regionu).

Więc masz! Opłata za zatwierdzenie wzrosła, ale zużycie pamięci fizycznej nie wzrosło.

Łatwo to zademonstrować za pomocą narzędzia sysinternals testlimit.

Jakiś czas później, powiedzmy, że program przechowuje coś (tj. Operację zapisu do pamięci) w tym regionie (nieważne gdzie). Pod żadnym regionem nie ma jeszcze fizycznej pamięci, więc taki dostęp spowoduje błąd strony . W odpowiedzi na którą menedżer pamięci systemu operacyjnego, a konkretnie procedura obsługi błędów stron (w skrócie „pager” ... nazywa się MiAccessFault):

  1. przydziel wcześniej dostępną stronę fizyczną
  2. skonfiguruj pozycję tabeli stron dla strony wirtualnej, do której uzyskano dostęp, aby powiązać numer strony wirtualnej z nowo przypisanym fizycznym numerem strony
  3. dodaj stronę fizyczną do prywatnego zestawu roboczego procesu
  4. i odrzuć błąd strony, powodując ponowienie instrukcji, która spowodowała błąd.

Teraz „zepsułeś” jedną stronę (4 KiB) w procesie. Wykorzystanie pamięci fizycznej odpowiednio wzrośnie, a „dostępna” pamięć RAM zmniejszy się. Opłata za zatwierdzenie nie zmienia się.

Jakiś czas później, jeśli strona nie była przez jakiś czas odsyłana, a zapotrzebowanie na pamięć RAM jest wysokie, może się to zdarzyć:

  1. system operacyjny usuwa stronę z zestawu roboczego procesu.
  2. ponieważ został napisany, odkąd został wprowadzony do zestawu roboczego, jest umieszczany na zmodyfikowanej liście stron (w przeciwnym razie przejdzie na listę stron rezerwowych). Wpis tabeli stron nadal odzwierciedla fizyczny numer strony pamięci RAM, ale teraz jego „poprawny” bit jest wyczyszczony, więc przy następnym odwołaniu wystąpi błąd strony
  3. gdy zmodyfikowana lista stron osiągnie mały próg, zmodyfikowany wątek piszący strony w procesie „System” budzi się i zapisuje zawartość zmodyfikowanych stron w pliku stronicowania (zakładając, że taki masz) i ...
  4. usuwa te strony ze zmodyfikowanej listy i umieszcza je na liście rezerwowej. Są teraz uważane za część „dostępnej” pamięci RAM; ale na razie wciąż mają swoją oryginalną zawartość z okresu, w którym byli w swoich procesach. Ponownie, opłata zatwierdzenia nie zmienia się, ale zużycie pamięci RAM i prywatny zestaw roboczy procesu spadną.
  5. Strony na liście rezerwowej można teraz zmienić przeznaczenie , co oznacza, że ​​są używane do czegoś innego - na przykład do usuwania błędów stron z dowolnego procesu w systemie lub używanego przez SuperFetch. Jednak...
  6. Jeśli proces, który utracił stronę na zmodyfikowanej lub rezerwowej liście, próbuje uzyskać do niej dostęp ponownie, zanim strona fizyczna zostanie zmieniona (tj. Nadal ma swoją oryginalną zawartość), błąd strony zostanie rozwiązany bez odczytu z dysku. Strona jest po prostu umieszczana z powrotem w zestawie roboczym procesu, a pozycja tabeli stron jest „ważna”. To jest przykład błędu strony „miękkiej” lub „taniej”. Mówimy, że listy rezerwowe i zmodyfikowane tworzą ogólnosystemową pamięć podręczną stron, które prawdopodobnie będą wkrótce potrzebne.

Jeśli nie masz pliku stronicowania, kroki od 3 do 5 są zmieniane na:

  1. Strony znajdują się na zmodyfikowanej liście, ponieważ nie ma gdzie napisać ich zawartości.

  2. Strony znajdują się na zmodyfikowanej liście, ponieważ nie ma gdzie napisać ich zawartości.

  3. Strony znajdują się na zmodyfikowanej liście, ponieważ nie ma gdzie napisać ich zawartości.

Krok 6 pozostaje taki sam, ponieważ strony na zmodyfikowanej liście mogą zostać zarzucone z powrotem do procesu, który utracił je jako błąd „miękkiej” strony. Ale jeśli tak się nie stanie, strony będą znajdować się na zmodyfikowanej liście, dopóki proces nie zwolni odpowiedniej pamięci wirtualnej (być może dlatego, że proces się kończy).

Istnieje inne wykorzystanie wirtualnej przestrzeni adresowej i pamięci RAM oprócz prywatnej pamięci zatwierdzonej. Istnieje odwzorowana wirtualna przestrzeń adresowa, dla której magazyn kopii zapasowych jest jakimś określonym plikiem, a nie plikiem strony. Strony zmapowanych waz, które są stronicowane, są odzwierciedlone w użyciu pamięci RAM, ale zmapowana pamięć nie przyczynia się do zatwierdzenia opłaty, ponieważ zmapowany plik zapewnia przechowywanie kopii zapasowych: Każda część zmapowanego regionu, która nie jest w pamięci RAM, jest po prostu przechowywana w plik odwzorowany. Inna różnica polega na tym, że większość mapowań plików może być współużytkowana przez procesy; udostępniona strona, która jest już w pamięci dla jednego procesu, może zostać dodana do innego procesu bez konieczności ponownego przechodzenia na dysk (kolejny błąd strony miękkiej).

I istnieją niestronicowane vas, dla których nie ma sklepu z podkładami, ponieważ zawsze jest rezydentem w pamięci RAM. Przyczynia się to zarówno do zgłaszanego użycia pamięci RAM, jak i do „opłaty zatwierdzenia”.

Wydaje się, że przyczyną może być kompresja. Co zmienia pytanie: Dlaczego limit nie zatwierdza, a nie idzie w górę czy coś takiego? Jaki jest sens kompresji, jeśli nie pomaga w zużyciu pamięci?

Nie. Nie ma to nic wspólnego z kompresją. Kompresja pamięci w systemie Windows odbywa się jako etap pośredni na stronach, które w przeciwnym razie zostałyby zapisane do pliku stronicowania. W efekcie pozwala zmodyfikowanej liście stron zużywać mniej pamięci RAM, aby pomieścić więcej rzeczy, przy pewnym koszcie czasu procesora, ale z dużo większą prędkością niż we / wy pliku strony (nawet na dysku SSD). Ponieważ limit zatwierdzania jest obliczany na podstawie całkowitej pamięci RAM + rozmiaru pliku strony, a nie użycia pamięci RAM + użycia pliku strony, nie wpływa to na limit zatwierdzania. Limit zatwierdzania nie zmienia się w zależności od tego, ile pamięci RAM jest w użyciu ani do czego jest używane.

Kiedy ładowanie się ładuje i Windows zaczyna prosić mnie o zamknięcie rzeczy, przez większość czasu pamięć fizyczna wynosi około 60%. To wydaje się okropnie nieefektywne.

Nie chodzi o to, że Windows jest nieefektywny. To aplikacje, które uruchamiasz. Popełniają o wiele więcej vas, niż faktycznie używają.

Powodem całego mechanizmu „opłaty zatwierdzenia” i „limitu zatwierdzenia” jest to: kiedy wywołuję VirtualAlloc, powinienem sprawdzić wartość zwracaną, aby zobaczyć, czy nie jest ona zerowa. Jeśli wynosi zero, oznacza to, że moja próba alokacji nie powiodła się, prawdopodobnie dlatego, że spowodowałaby, że opłata za zatwierdzenie przekroczyła limit zatwierdzenia. Powinienem zrobić coś rozsądnego, np. Spróbować popełnić mniej lub wyjść z programu czysto.

Jeśli VirtualAlloc zwróci wartość niezerową, tj. Adres, który mówi mi, że system złożył gwarancję - zobowiązanie, jeśli chcesz - że niezależnie od liczby bajtów, o które prosiłem, zaczynając od tego adresu, będzie dostępnych, jeśli zdecyduję się uzyskać do nich dostęp; że jest miejsce, w którym można to wszystko umieścić - albo pamięć RAM, albo plik stronicowania. tzn. nie ma powodu, aby oczekiwać jakiegokolwiek niepowodzenia w dostępie do czegokolwiek w tym regionie. To dobrze, ponieważ nie byłoby rozsądne oczekiwać, że sprawdzę, czy „zadziałało?” przy każdym dostępie do przydzielonego regionu.

Analogia „banku pożyczającego pieniądze”

To trochę jak bank oferujący kredyty, ale wyłącznie gotówka. (To nie jest oczywiście sposób działania prawdziwych banków.)

Załóżmy, że bank zaczyna od gotówki w wysokości miliona dolarów. Ludzie chodzą do banku i proszą o linie kredytowe w różnych kwotach. Powiedzmy, że bank zatwierdza mnie na linię kredytową w wysokości 100 000 USD (tworzę prywatny region, w którym przyznano środki); to nie znaczy, że jakakolwiek gotówka opuściła skarbiec. Jeśli później rzeczywiście wezmę pożyczkę na, powiedzmy, 20 000 USD (uzyskuję dostęp do podzbioru regionu), spowoduje to usunięcie gotówki z banku.

Ale niezależnie od tego, czy zaciągnę jakieś pożyczki, czy nie, fakt, że zostałem zatwierdzony na maksymalnie 100 000 USD, oznacza, że ​​bank może następnie zatwierdzić kolejne linie kredytowe o łącznej wartości 900 000 USD dla wszystkich swoich klientów. Bank nie zatwierdzi kredyt w nadmiarze swoich rezerw pieniężnych (czyli nie będzie overcommitu je), ponieważ oznaczałoby to bank może trzeba włączyć wcześniej zatwierdzony kredytobiorcy z dala kiedy później pokazać się z zamiarem wykupienia ich kredyt . Byłoby to bardzo złe, ponieważ bank już zobowiązał się do udzielenia tych pożyczek, a reputacja banku gwałtownie spadłaby.

Tak, jest to „nieefektywne” pod względem wykorzystania tej gotówki przez bank. Im większa jest różnica między liniami kredytowymi, na które klienci są zatwierdzeni, a kwotami, które faktycznie pożyczają, tym mniej jest to efektywne. Ale ta nieefektywność nie jest winą banku; to „wina” klientów za to, że proszą o tak wysokie linie kredytowe, a jedynie zaciągają niewielkie pożyczki.

Model biznesowy banku polega na tym, że po prostu nie może odrzucić wcześniej zatwierdzonego pożyczkobiorcy, kiedy pojawia się, aby uzyskać pożyczkę - byłoby to dla klienta „śmiertelne”. Dlatego bank uważnie śledzi, ile funduszy pożyczkowych zostało „zaangażowanych”.

Podejrzewam, że rozszerzenie pliku strony lub dodanie innego byłoby jak wyjście banku i zdobycie większej ilości gotówki i dodanie jej do funduszu pożyczkowego.

Jeśli chcesz zamodelować zmapowaną i niestronicowaną pamięć w tej analogii ... niestronicowana jest jak mała pożyczka, którą musisz wyjąć i trzymać z daleka po otwarciu konta. (Niestronicowe struktury, które definiują każdy nowy proces.) Odwzorowana pamięć jest jak zabranie ze sobą własnej gotówki (pliku, który jest mapowany) i zdeponowanie jej w banku, a następnie wyjęcie tylko jej części na raz (stronicowanie). Dlaczego by nie umieścić wszystkich stron jednocześnie? Nie wiem, może nie masz miejsca w portfelu na te wszystkie pieniądze. :) Nie wpływa to na zdolność innych osób do pożyczania pieniędzy, ponieważ wpłacone środki pieniężne znajdują się na Twoim koncie, a nie w ogólnym funduszu pożyczkowym. Ta analogia zaczyna się tam załamywać, zwłaszcza gdy zaczynamy myśleć o pamięci wspólnej, więc nie przesadzaj.

Powrót do systemu operacyjnego Windows: fakt, że większość pamięci RAM jest „dostępna”, nie ma nic wspólnego z opłatą zatwierdzania i limitem zatwierdzania. Jeśli zbliżasz się do limitu zatwierdzeń, oznacza to, że system operacyjny już zatwierdził - tj. Obiecał udostępnić, gdy zostaniesz o to poproszony - tyle pamięci. Nie musi być jeszcze w użyciu, aby można było wprowadzić limit.

Czy mogę zrezygnować ze sztucznego pompowania pliku strony do poziomów, w których mój głodny SSD jest źle wyposażony do obsługi, tak aby faktycznie móc efektywnie wykorzystać moją pamięć fizyczną? (Lub nawet jeśli nie byłby tak pełny. To znaczy, chciałbym unikać sugestii typu „Do X / Y / Z do pliku strony”.)

Przykro mi, ale jeśli napotykasz limit zatwierdzeń, możesz zrobić tylko trzy rzeczy:

  1. Zwiększ swoją pamięć RAM.
  2. Zwiększ rozmiar pliku strony.
  3. Uruchamiaj mniej rzeczy za jednym razem.

Re opcja 2: Możesz umieścić drugi plik stronicowania na dysku twardym. Jeśli aplikacje nie wykorzystują całej zajętej pamięci - która najwyraźniej tak nie jest, ponieważ widzisz tak dużo wolnej pamięci RAM - tak naprawdę nie będziesz mieć dostępu do tego pliku strony, więc umieszczenie go na dysku twardym nie spowoduje zaszkodzić wydajności. Jeśli powolność dysku twardego nadal Ci przeszkadza, inną opcją jest zdobycie małego, a zatem taniego drugiego dysku SSD i umieszczenie na nim drugiego pliku stronicowania. Jednym z „showstopperów” byłby laptop bez możliwości dodania drugiego „nieusuwalnego” napędu. (Windows nie pozwoli ci umieszczać plików stronic na dyskach wymiennych, jak wszystko połączone z USB.)

Oto kolejna odpowiedź, którą napisałem, która wyjaśnia wszystko z innego kierunku.

ps: Pytałeś o Windows 10, ale powinienem powiedzieć, że działa on tak samo w każdej wersji rodziny NT, z powrotem do NT 3.1, a także w wersjach wstępnych. To, co najprawdopodobniej uległo zmianie, to domyślne ustawienie rozmiaru pliku stronicowania w Windows, z 1,5x lub 1x RAM do znacznie mniejszego. Uważam, że to był błąd.

Jamie Hanrahan
źródło
1
+1 To jest odpowiedź, którą chciałbym napisać. Właśnie tak działa nowoczesny system operacyjny. Nie było problemu przed dyskami SSD, ponieważ nie mieliśmy dużo pamięci RAM i mieliśmy dużo miejsca na dysku twardym. Teraz, gdy mamy dużo pamięci RAM i nie tyle pamięci masowej na niektórych komputerach, wystarczająca przestrzeń plików stronicowania staje się znowu problemem. Postaw na priorytet, aby Twoje urządzenie mogło efektywnie wykorzystywać pamięć RAM.
David Schwartz
@DavidSchwartz: Widziałem wiele twoich odpowiedzi na temat MM i muszę powiedzieć, że pochodzi od ciebie bardzo pochwała. Dziękuję Ci.
Jamie Hanrahan,
Światło świeciło. To wszystko (cóż, większość) ma wreszcie sens. Przeczytaj tę i swoją drugą odpowiedź, każda z nich oferuje nowe informacje. Kusi mnie nawet, aby wyśledzić książkę. W szczególności zadałem to pytanie najpierw na forum wewnętrznym (jak sugeruje wymiana komentarzy pod pytaniem), ale wydaje się nieco martwe. To, co powiedział Dawid, jest również prawdą. To pytanie jest w pewnym sensie nieco przestarzałe, ponieważ mam teraz nowy dysk SSD i mogę sobie pozwolić na dodatkowy plik stronicowania, ale był to prawdziwy problem z moim poprzednim bardzo małym dyskiem. ... ciąg dalszy poniżej ...
martixy
... kontynuował z góry. Nawiasem mówiąc, w moich własnych badaniach odkryłem, że nie jest to jedyny sposób na robienie rzeczy, ponieważ Linux i wiele hypervisorów VM ma opcję o nazwie „overcommit”. W rzeczywistości wydaje się, że Windows jest w mniejszości, jeśli chodzi o podejście do alokacji pamięci. Aha, i kiedy o tym myślę, wymyśliłem mniej więcej tę samą analogię bankową. Zbieg okoliczności jest niesamowity.
martixy
Ale te opcje „nadmiernego zaangażowania” nie zawsze odnoszą się do tej konkretnej koncepcji. Pamięć wirtualna w systemie operacyjnym ogólnego przeznaczenia, gdy system operacyjny powie ci „ok, alokacja się powiodła”, ma działać na programistę jak pamięć fizyczna ... z wyjątkiem niewielkiego opóźnienia, które może wystąpić od czasu do czasu, gdy wystąpi błąd strony . Problem z dopuszczeniem nadpisywania całej pamięci fizycznej, która może realizować wirtualną, polega na tym, że proste odniesienia pamięci, takie jak i = * j; może powodować błędy krytyczne , nawet jeśli i jest na twoim stosie, a j został wcześniej zwrócony jako rzekomo poprawny wskaźnik. (ciąg dalszy ...)
Jamie Hanrahan,