Czy pamięć „buforowana” jest faktycznie wolna?

11

Podczas uruchamiania cat /proc/meminfona górze znajdują się 3 wartości:

MemTotal:        6291456 kB
MemFree:         4038976 kB
Cached:          1477948 kB

O ile mi wiadomo, wartość „Cached” to pamięci podręczne dysków tworzone przez system Linux, które zostaną natychmiast zwolnione, jeśli jakakolwiek aplikacja potrzebuje więcej pamięci RAM, dlatego Linux nigdy nie zabraknie pamięci, dopóki zarówno MemFree, jak i Cache nie osiągną zera.

Niestety „MemAvailable” nie jest zgłaszane przez / proc / meminfo, prawdopodobnie dlatego, że działa na serwerze wirtualnym. (Wersja jądra to 4.4)

Tak więc dla wszystkich praktycznych celów pamięć RAM dostępna dla aplikacji to MemFree + Cache.

Czy ten widok jest poprawny?

Roland Seuhs
źródło
1
Nie chcę młotkować złota tak zamkniętego, ale to pytanie jest istotne, jeśli nie duplikat. Dziwię się, że nie masz MemAvailable, został dodany w wersji 3.14.
Stephen Kitt
W zaakceptowanej odpowiedzi z tego pytania użyto / proc / zoneinfo, które nie jest również dostępne w moim
vserverie
uname -a: Host Linux 4.4.0-042stab134.8 # 1 SMP Pt Dec 7 17:16:09 MSK 2018 x86_64 x86_64 x86_64 GNU / Linux
Roland Seuhs
Podejrzewam, że jest to system OpenVZ z jądrem opartym na wersji 2.6.32, a nie 4.4.
Stephen Kitt
1
@sourcejedi i został skompilowany dokładnie w tym samym czasie co jądro 4.4!
Stephen Kitt,

Odpowiedzi:

10

Ten pogląd może być bardzo mylący w wielu rzeczywistych przypadkach.

Jądro zapewnia teraz oszacowanie dostępnej pamięci w MemAvailableterenie. Ta wartość znacznie różni się od MemFree + Cached.

/ proc / meminfo: zapewnia szacunkową dostępną pamięć [opis zmiany jądra, 2014]

Wiele programów do równoważenia obciążenia i umieszczania obciążenia sprawdza / proc / meminfo, aby oszacować, ile wolnej pamięci jest dostępne. Na ogół robią to, dodając „darmowy” i „buforowany”, co było w porządku dziesięć lat temu, ale jest prawie pewne, że dzisiaj się myli.

Jest to błędne, ponieważ pamięć podręczna obejmuje pamięć, której nie można zwolnić jako pamięć podręczną strony, na przykład segmenty pamięci współużytkowanej, tmpfs i ramfs, i nie obejmuje pamięci płyty, którą można odzyskać, która może zajmować dużą część pamięci systemowej w większości bezczynnych systemów z dużo plików.

Obecnie ilość pamięci dostępnej dla nowego obciążenia, bez popychania systemu do zamiany, można oszacować na podstawie MemFree, Active (plik), Inactive (plik) i SReclaimable, a także „niskich” znaków wodnych z / proc / zoneinfo. Może się to jednak zmienić w przyszłości i naprawdę nie należy oczekiwać, że przestrzeń użytkownika zna wewnętrzne jądra w celu oszacowania ilości wolnej pamięci. Bardziej wygodne jest podanie takiego oszacowania w / proc / meminfo. Jeśli coś się zmieni w przyszłości, musimy to zmienić tylko w jednym miejscu.
...

Dokumentacja / systemy plików / proc.txt:
...
MemAvailable: Szacunkowa ilość pamięci dostępnej do uruchamiania nowych aplikacji, bez zamiany. Obliczony na podstawie MemFree, SReclaimable, rozmiar list LRU pliku i niskie znaki wodne w każdej strefie. Szacunek bierze pod uwagę, że system potrzebuje pewnej pamięci podręcznej stron, aby dobrze funkcjonować, i że nie wszystkie płyty, które można odzyskać, będą możliwe do odzyskania z powodu wykorzystywania elementów. Wpływ tych czynników będzie się różnił w zależności od systemu.

1. Szczegóły MemAvailable

Jak wspomniano powyżej, tmpfs i inna Shmempamięć nie mogą zostać zwolnione, a jedynie przeniesione do zamiany. Cachedw /proc/meminfomoże być bardzo mylące, w tym ze względu na to swap Shmempamięci. Jeśli masz zbyt wiele plików w tmpfs, może to zajmować dużo pamięci :-). Shmemmoże również obejmować niektóre przydziały pamięci graficznej , które mogą być bardzo duże.

MemAvailablecelowo nie obejmuje pamięci wymiennej. Zbyt duża zamiana może powodować duże opóźnienia. Być może zdecydowałeś się uruchomić bez przestrzeni wymiany, lub zezwoliłeś tylko na względnie ograniczoną ilość.

Musiałem dokładnie sprawdzić, jak MemAvailabledziała. Na pierwszy rzut oka wydaje się, że kod nie wspomina o tym rozróżnieniu.

/*
 * Not all the page cache can be freed, otherwise the system will
 * start swapping. Assume at least half of the page cache, or the
 * low watermark worth of cache, needs to stay.
 */
pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
pagecache -= min(pagecache / 2, wmark_low);
available += pagecache;

Stwierdziłem jednak, że poprawnie traktuje Shmemjako pamięć „używaną”. Utworzyłem kilka plików 1GB w tmpfs. Każdy wzrost o 1 GB Shmemzmniejsza się MemAvailableo 1 GB. Zatem rozmiar „list LRU pliku” nie obejmuje pamięci współdzielonej ani żadnej innej pamięci wymiennej. (Zauważyłem, że te same liczby stron są również używane w kodzie obliczającym „brudny limit” ).

Ta MemAvailablekalkulacja zakłada również, że chcesz zachować przynajmniej na tyle, aby dorównać pamięci podręcznej plików jądra „niski” znak wodny. Lub połowa bieżącej pamięci podręcznej - w zależności od tego, która wartość jest mniejsza. (To samo dotyczy również płyt podlegających zwrotowi). „Niski znak wodny” jądra można dostroić, ale zwykle jest to około 2% pamięci RAM systemu . Więc jeśli chcesz tylko z grubsza oszacować, możesz zignorować tę część :-).

Jeśli korzystasz firefoxz około 100 MB kodu programu zmapowanego w pamięci podręcznej strony, zazwyczaj chcesz zachować to 100 MB w pamięci RAM :-). W przeciwnym razie w najlepszym wypadku wystąpią opóźnienia, w najgorszym przypadku system będzie spędzał cały czas na rzucaniu się między różnymi aplikacjami. Pozwala więc na MemAvailableto niewielki procent pamięci RAM. Może to nie wystarczać lub może być zbyt hojne. „Wpływ tych czynników będzie się różnił w zależności od systemu”.

W przypadku wielu obciążeń komputerów punkt „wiele plików” może nie być istotny. Mimo to mam obecnie 500 MB pamięci do odzyskania na płycie w moim laptopie (z 8 GB pamięci RAM). Wynika to z ext4_inode_cache(ponad 300 000 obiektów). Stało się tak, ponieważ ostatnio musiałem przeskanować cały system plików, aby znaleźć, co wykorzystuje moje miejsce na dysku :-). Użyłem polecenia df -x / | sort -n, ale np. Gnome Disk Usage Analyzer zrobiłby to samo.

2. [edycja] Pamięć w grupach kontrolnych

Tak zwane „Linux” pojemniki są zbudowane z namespaces, cgroupsi różne inne funkcje, w zależności od gustu :-). Mogą zapewnić wystarczająco przekonujące środowisko, aby uruchomić coś prawie jak pełny system Linux. Usługi hostingowe mogą budować takie kontenery i sprzedawać je jako „serwery wirtualne” :-).

Serwery hostingowe mogą również budować „serwery wirtualne” przy użyciu funkcji, których nie ma w głównym Linuksie. Kontenery OpenVZ wcześniej datują grupy główne o dwa lata i mogą używać „beancounters” w celu ograniczenia pamięci. Nie możesz więc dokładnie zrozumieć, jak działają te limity pamięci, jeśli czytasz tylko dokumenty lub zadajesz pytania dotyczące głównego jądra Linuksa. cat /proc/user_beancounterspokazuje aktualne użycie i ograniczenia. vzubcprezentuje go w nieco bardziej przyjaznym formacie. Strona główna beancounters dokumentuje nazwy wierszy.

Grupy kontrolne obejmują możliwość ustawiania limitów pamięci dla procesów w nich zawartych. Jeśli uruchomisz aplikację w takiej grupie, nie cała pamięć systemowa będzie dostępna dla aplikacji :-). Jak więc widzimy dostępną pamięć w tym przypadku?

Interfejs do tego różni się na wiele sposobów, w zależności od tego, czy używasz cgroup-v1 czy cgroup-v2 .

Instalacja mojego laptopa używa cgroup-v1. Mogę uruchomić cat /sys/fs/cgroup/memory/memory.stat. Z akt sprawy wynika wielu dziedzinach, takich total_rss, total_cache, total_shmem. shmem, w tym tmpfs, wlicza się do limitów pamięci. Myślę, że można spojrzeć na total_rssodwrotny odpowiednik MemFree. Jest też plik memory.kmem.usage_in_bytesreprezentujący pamięć jądra, w tym płyty. (Zakładam, że memory.kmem.zawiera także memory.kmem.tcp.wszelkie przyszłe rozszerzenia, chociaż nie jest to wyraźnie udokumentowane). Nie ma osobnych liczników, aby wyświetlić pamięć płyty, którą można odzyskać. Dokument dla cgroup-v1 mówi, że przekroczenie limitów pamięci nie powoduje odzyskania żadnej pamięci płyty. (Dokument zawiera również oświadczenie, że jest „beznadziejnie nieaktualny” i że powinieneś sprawdzić aktualny kod źródłowy).

cgroup-v2 jest inny. Myślę, że grupa główna (najwyższego poziomu) nie obsługuje rozliczania pamięci. cgroup-v2 nadal ma memory.statplik. Wszystkie pola sumują się nad grupami podrzędnymi, więc nie trzeba szukać total_...pól. Istnieje filepole, co oznacza, że ​​to samo cachezrobiło. Irytujące nie widzę takiego pola jak w rssśrodku memory.stat; Myślę, że musiałbyś zsumować poszczególne pola. Istnieją osobne statystyki dla pamięci płyty, którą można odzyskać i której nie można odzyskać; Myślę, że grupa cg2 v2 została zaprojektowana do odzyskiwania płyt, gdy zaczyna brakować pamięci.

Grupy linuksowe nie wirtualizują się automatycznie /proc/meminfo(ani żadnego innego pliku /proc), więc pokazywałyby wartości dla całego komputera. Myliłoby to klientów VPS. Można jednak użyć przestrzeni nazw, aby zastąpić /proc/meminfoplikiem sfałszowanym przez określone oprogramowanie kontenera . Jak przydatne są fałszywe wartości, zależy od tego, co robi to konkretne oprogramowanie.

systemduważa, że ​​cgroup-v1 nie może być bezpiecznie delegowany np. do kontenerów. systemd-nspawnZajrzałem do pojemnika w moim systemie cgroup-v1. Widzę grupę, w której został umieszczony, i pamięć na tym. Z drugiej strony zawarte systemdnie tworzy zwykłych grup usług dla rozliczania zasobów. Jeśli rozliczanie pamięci nie zostało włączone w tej grupie, zakładam, że kontener nie będzie mógł go włączyć.

Zakładam, że jeśli jesteś w kontenerze cgroup-v2, będzie on wyglądał inaczej niż katalog główny prawdziwego systemu cgroup-v2 i będziesz w stanie zobaczyć pamięć odpowiadającą za grupę cgroup najwyższego poziomu. Lub jeśli cgroup, którą widzisz, nie ma włączonego rozliczania pamięci, mam nadzieję, że będziesz miał uprawnienia delegowane, aby móc włączyć rozliczanie pamięci wsystemd (lub równoważnym).

sourcejedi
źródło
1
to clicky nao. Korzystam z łączy GitHub, ponieważ pokazują one pierwsze wydanie zawierające zatwierdzenie (podobne dogit describe --contains ). Stwierdzono, że jest połączony jako TL; DR przez pytanie SU, które okazało się po prostu cytując sekcję dodaną do proc.txt. Ale w przypadku tego pytania opis zatwierdzenia jest po prostu idealny IMO :-).
sourcejedi
Wydaje się, że MemAvailable nie jest dostępna na większości serwerów wirtualnych ... co zatem zrobić?
Roland Seuhs
@RolandSeuhs prawdopodobnie uczy się „beancounters”. Zobacz zmiany pogrubione. Jeśli masz pytanie dotyczące beancounters, byłbym wdzięczny, jeśli zadasz nowe pytanie. Zawsze możemy link do tego z tego, ale szczegóły prawdopodobnie nie są istotne dla czytelników, którzy używają jądra Linuxa.
sourcejedi