Pamieć wirtualna w Windows

0

Mam Windows 8 64-bit na dysku SSD i 4GB pamięci RAM. W systemie ustawiłem 16GB pamięci wirtualnej.

O ile dobrze rozumiem, czym jest pamięć wirtualna, to ja to wyobrażam sobie, że jest to powiększenie pamięci operacyjnej w taki sposób, że część jest w pamięci RAM, a reszta jest na dysku i system na bieżąco decyduje, który fragment pamięci operacyjnej jest w pamięci RAM, podczas, gdy reszta jest na dysku. Program powinien mieć wrażenie, że ma do dyspozycji większą ilość pamięci operacyjnej niż zainstalowana w pamięci RAM. A to, że część danych jest na dysku, a nie w pamięci RAM, to program o tym nie wie i nie jest dla niego ważne. Dlatego to się nazywa "pamięć wirtualna".

Okazuje się, że menedżer zadań pokazuje, że mam 4GB pamięci operacyjnej, ponad połowa wypełniona. Niedawno testowałem pewną implementację, to program wywalał się wyjątkiem "OutofmemoryException" zaraz po zapełnieniu się wolnej pamięci z tych 4GB.

Wobec powyższego, powinno być 20GB pamięci operacyjnej, a tak nie jest. Z czego to wynika?

Jak zmusić system, żeby udostępniał 16 lub 20GB pamięci. Niech sobie przerzuca dane pomiędzy dyskiem, a pamięcią RAM, ale niech program dostanie większą pamięć, tylko będzie działać z mniejszą wydajnością z powodu przerzucania danych i faktu, że dysk jest wolniejszy od RAM.

0

Pytanie czy aplikacja była skompilowana pod x64 :)
Do poczytania: https://pl.m.wikipedia.org/wiki/Pami%C4%99%C4%87_wirtualna

0

To nie jest do końca tak jak pisze, to jest dużo bardziej skomplikowane.

0

Np. w takim C# bodajże trzeba w solucji parę zezwoleń dopisać by wyjść po za ~4 Gb ramu. W dodatku nie wiem czy ram wirtualny jest taki sam jak zwykły. Nie wspomnę o różnicy w czasie dostępu pomiędzy ramem a wirtualnym ramem. https://stackoverflow.com/questions/8563933/c-sharp-out-of-memory-exception tutaj jest też przekład, że język może ograniczać maksymalną do zalokowania pamieć per objekt.

1
andrzejlisek napisał(a):Niedawno testowałem pewną implementację, to program wywalał się wyjątkiem "OutofmemoryException" zaraz po zapełnieniu się wolnej pamięci z tych 4GB.

Jeśli program jest 32-bitowy to normalnie ma dostęp do 4-gigabajtowej przestrzeni adresowej. Używanie więcej RAM-u w 32-bitowym programie jest możliwe, ale skomplikowane. Łatwiej po prostu program skompilować jako 64-bitowy.

0

Akurat w tym przypadku aplikacja była skompilowana jako 32-bity, ale bariera 4GB nie ma tu nic do tego. Akurat to był C#, ale technologia samej aplikacji też chyba nie ma znaczenia. Dla systemu aplikacja (lub maszyna CLI bądź Java) po prostu zgłasza zapotrzebowanie na coraz to kolejne porcje pamięci, a system albo przydziela, albo odmawia, jak nie może przydzielić. Załóżmy, że menedżer zadań pokazuje, że zajęte jest 3GB, potem 500MB jest opisana jako "wstrzymana", ostatnie 500MB jest wolny. Uruchamiam program i wystarczy, że zacznie zajmować 500MB lub 1GB (nie pamiętam teraz, musiałbym sprawdzić) to już się wywala.

Załóżmy, że aplikacja chce 100MB pamięci. Wystarczy, że system wybierze sobie te 100MB danych z RAM, przerzuci sobie na dysk powodując spowolnienie pracy innych aplikacji i aplikacja może dostać te 100MB pamięci w RAM. Albo też system zdecyduje, że aplikacja dostanie żądaną ilość pamięci, jednak ta pamięć będzie na dysku, co spowoduje zmniejszenie szybkości zapisu i odczytu danych. Naprawdę, nie da się tak zrobić? Nawet się mówi, że "system swapuje", bo inna nazwa to "swap memory", a objawia się to spowolnieniem pracy całego systemu, bo system śledząc zapotrzebowanie na użycie co chwilę przerzuca fragmenty pamięci operacyjnej pomiędzy RAM a dyskiem zgodnie z zapotrzebowaniem aplikacji.

W przypadku zwykłego dysku, różnica w wydajności zapisu i odczytu jest kolosalna. W przypadku SSD powinna być dużo mniejsza. Z tego powodu założyłem pamięć wirtualną na SSD.

3
andrzejlisek napisał(a):

Akurat w tym przypadku aplikacja była skompilowana jako 32-bity, ale bariera 4GB nie ma tu nic do tego.

Ma dużo, bo jeżeli chcesz gigabajta pamięci w jednym kawałku, to może się okazać że w ramach 4-gigabajtowej przestrzeni adresowej nie ma takiego jednego wolnego kawałka gdzie by można było ten gigabajt umieścić.
Może się okazać że nie da się zaalokować 1 GB na raz, ale może się dać dziesięć razy po 100 mega, albo sto razy po 10 mega.

64-bitowa aplikacja raczej nie miałaby takiego problemu, bo dostępna przestrzeń adresowa jest ogromna.

1

Akurat w tym przypadku aplikacja była skompilowana jako 32-bity, ale bariera 4GB nie ma tu nic do tego.

Moze jednak troche mieć ;) Moze też być tak że maszyna wirtualna ma ustawienia (JVM ma) ile maksymalnie pamięci może zaalokować i możesz mieć i 1TB ramu, a jak ustawiłeś że aplikacja ma nie brać wiecej niż 10MB to też poleci ci OutOfMemory

W przypadku zwykłego dysku, różnica w wydajności zapisu i odczytu jest kolosalna. W przypadku SSD powinna być dużo mniejsza. Z tego powodu założyłem pamięć wirtualną na SSD.

Ale rozumiesz ze ten SSD długo w takiej sytuacji nie pożyje?

1

Pamięć wirtualna służy raczej do upchnięcia więcej programów niż do zaalokowania większych bloków danych.
Możesz spróbować pamięci mapowanej na pliki, w takim rozwiązaniu masz chyba większą kontrolę nad tym co się dzieje z Twoim blokiem danych.
Nie znam C# ani nie pracowałem z takimi plikami, ale tu masz opis:
https://docs.microsoft.com/pl-pl/dotnet/standard/io/memory-mapped-files
https://www.infoworld.com/article/2898365/working-with-memory-mapped-files-in-net.html
https://www.c-sharpcorner.com/UploadFile/b942f9/using-memory-mapped-files/

Tu artykuł który też proponuje to rozwiązanie:
https://accu.org/index.php/journals/1875

1 użytkowników online, w tym zalogowanych: 0, gości: 1