TL; DR
Krótki tymczasowy / odpowiedź
- Najłatwiej : Miej mniejszą partycję wymiany i unikaj, aby jądro próbowało sprostać kłamstwu, że nie ma limitu pamięci, uruchamiając procesy z wolnej pamięci.
- Przy dużej wymianie OOM (menedżer pamięci) nie podejmuje wystarczająco szybko działań. Zazwyczaj rozlicza się zgodnie z pamięcią wirtualną i, zgodnie z moim przeszłym doświadczeniem, nie zabijał rzeczy, dopóki cała wymiana nie została zapełniona, stąd system thrash and crawling ...
- Potrzebujesz dużej zamiany na hibernację?
- Próba / problematyka : Ustaw niektóre limity (np. Sprawdź
ulimit -v
, a może ustaw sztywny lub miękki limit za pomocą as
opcji w limits.conf
). Kiedyś działało to wystarczająco dobrze, ale dzięki wprowadzeniu WebKit gigacage
wiele aplikacji gnome oczekuje teraz nieograniczonej przestrzeni adresowej i nie działa!
- Usiłował / problematyczne : Polityka overcommitu i stosunek jest kolejnym sposobem, aby spróbować zarządzać i złagodzić ten (na przykład
sysctl vm.overcommit_memory
, sysctl vm.overcommit_ratio
ale takie podejście nie działa dla mnie.
- Trudne / skomplikowane : spróbuj zastosować priorytet cgroup do najważniejszych procesów (np. Ssh), ale obecnie wydaje się to kłopotliwe dla cgroup v1 (mam nadzieję, że v2 ułatwi to) ...
Znalazłem też:
Rozwiązanie długoterminowe
poczekaj i mam nadzieję, że niektóre łatki wcześniejsze wejdą do stabilnych jąder dystrybucji. Miej również nadzieję, że dostawcy dystrybucji lepiej dostroją ustawienia domyślne jądra i lepiej wykorzystają grupy systemowe, aby priorytetowo reagować na GUI w wydaniach na komputery stacjonarne.
Niektóre interesujące łatki:
Zatem winny jest nie tylko zły kod przestrzeni użytkownika i konfiguracja / ustawienia domyślne dystrybucji - jądro może to lepiej obsłużyć.
Komentarze do rozważanych już opcji
1) Wyłącz zamianę
Zalecane jest zapewnienie przynajmniej małej partycji wymiany ( czy naprawdę potrzebujemy wymiany w nowoczesnych systemach? ). Wyłączenie zamiany nie tylko zapobiega zamianie nieużywanych stron, ale może również wpływać na domyślną heurystyczną strategię nadmiernego zatwierdzania pamięci przez jądro w celu alokacji pamięci ( co oznacza heurystyka w Overcommit_memory = 0? ), Ponieważ ta heurystyka ma znaczenie dla stron wymiany. Bez zamiany overcommit nadal prawdopodobnie działa w trybie heurystycznym (0) lub zawsze (1), ale połączenie strategii no swap i nigdy (2) strategii overcommit jest prawdopodobnie okropnym pomysłem. W większości przypadków żadna zamiana prawdopodobnie nie zaszkodzi wydajności.
Na przykład pomyśl o długotrwałym procesie, który początkowo dotyka pamięci w celu jednorazowej pracy, ale potem nie zwalnia pamięci i działa w tle. Jądro będzie musiało używać do tego pamięci RAM, dopóki proces się nie zakończy. Bez wymiany jądro nie może znaleźć strony, która chciałaby aktywnie korzystać z pamięci RAM. Zastanów się także, ilu programistów jest leniwych i nie zwalnia wprost pamięci po użyciu.
3) ustaw maksymalny limit pamięci
Dotyczy to tylko jednego procesu i prawdopodobnie jest to rozsądne założenie, że proces nie powinien żądać więcej pamięci niż system fizycznie! Prawdopodobnie więc warto powstrzymać samotny szalony proces przed wyzwalaniem thrashingu, będąc jednocześnie hojnie nastawionym.
4) przechowuj ważne programy (X11, bash, kill, top, ...) w pamięci i nigdy ich nie wymieniaj
Fajny pomysł, ale wtedy te programy wymażą pamięć, której nie używają aktywnie. Dopuszczalne może być, jeśli program zażąda tylko niewielkiej ilości pamięci.
Wydanie systemd 232 właśnie dodało kilka opcji, które to umożliwiają: Myślę, że można użyć „MemorySwapMax = 0”, aby zapobiec wymianie pamięci przez jednostkę (usługę), taką jak ssh.
Niemniej jednak lepszym rozwiązaniem byłoby ustalenie priorytetu dostępu do pamięci.
Długie wyjaśnienie
Jądro Linuksa jest lepiej dostrojone do obciążeń serwera, więc reakcja GUI była niestety drugorzędną kwestią ... Ustawienia zarządzania pamięcią jądra w wersji Ubuntu 16.04 LTS na pulpicie nie różniły się od innych wersji serwera. Jest nawet zgodny z domyślnymi w RHEL / CentOS 7.2 zwykle używanym jako serwer.
OOM, ulimit i kompromis uczciwość dla reaktywności
Wymiana thrash (gdy działający zestaw pamięci, tj. Strony odczytywane i zapisywane w danym krótkim przedziale czasowym przekraczają fizyczną pamięć RAM) zawsze blokuje pamięć I / O pamięci - żadne działanie jądra nie może uratować systemu przed zabiciem procesu lub dwa...
Mam nadzieję, że poprawki Linux OOM pojawiające się w nowszych jądrach rozpoznają, że ten zestaw roboczy przekracza sytuację w pamięci fizycznej i zabija proces. Kiedy tak się nie dzieje, pojawia się problem z drżeniem. Problem polega na tym, że przy dużej partycji wymiany może wyglądać, jakby system nadal miał nadmiar, podczas gdy jądro wesoło przesuwa się i obsługuje żądania pamięci, ale zestaw roboczy może przelać się na wymianę, skutecznie próbując traktować pamięć tak, jakby to RAM.
Na serwerach akceptuje karę za wydajność polegającą na przerzucaniu za określone, wolne, nie tracące danych, kompromisy. Na komputerach kompromis jest inny i użytkownicy wolą trochę utraty danych (poświęcenie procesu), aby zachować szybkość reakcji.
To była fajna komiczna analogia do OOM: oom_pardon, czyli nie zabijaj mojego xlocka
Nawiasem mówiąc, OOMScoreAdjust
jest kolejną systemową opcją, która pomaga ważyć i unikać procesów zabijania OOM, uważanych za ważniejsze.
buforowany zapis zwrotny
Myślę, że „ Spraw, aby zapisywanie w tle nie było do bani ” pomoże uniknąć pewnych problemów, w których proces zapełniający pamięć RAM powoduje kolejną zamianę (zapis na dysk), a masowe zapisywanie na dysk zatrzymuje wszystko, co chce IO. Sam problem nie jest przyczyną przeładowania, ale przyczynia się do ogólnego pogorszenia reakcji.
ogranicza ograniczenia
Jednym z problemów z ulimits jest to, że rozliczanie limitu dotyczy przestrzeni adresowej pamięci wirtualnej (co oznacza łączenie zarówno przestrzeni fizycznej, jak i przestrzeni wymiany). Zgodnie z man limits.conf
:
rss
maximum resident set size (KB) (Ignored in Linux 2.4.30 and
higher)
Tak więc ustawienie ulimit tak, aby dotyczyło tylko fizycznego użycia pamięci RAM, nie wygląda już na użyteczne. Stąd
as
address space limit (KB)
wydaje się być jedynym szanowanym dostrajaniem.
Niestety, jak szczegółowo opisano na przykładzie WebKit / Gnome, niektóre aplikacje nie mogą działać, jeśli przydzielanie wirtualnej przestrzeni adresowej jest ograniczone.
cgroups powinien pomóc w przyszłości?
Obecnie wydaje się to kłopotliwe, ale możliwe jest włączenie niektórych flag cgroup jądra cgroup_enable=memory swapaccount=1
(np. W grub config), a następnie spróbuj użyć kontrolera pamięci cgroup, aby ograniczyć użycie pamięci.
Grupy c mają bardziej zaawansowane funkcje limitu pamięci niż opcje „ulimit”. Notatki CGroup v2 wskazują na próby poprawy działania ulimits.
Połączona pamięć + ewidencjonowanie i ograniczanie wymiany są zastępowane przez rzeczywistą kontrolę nad przestrzenią wymiany.
Opcje CGroup można ustawić za pomocą opcji systemowej kontroli zasobów . Na przykład:
Inne przydatne opcje mogą być
Mają one pewne wady:
- Nad głową. Obecna dokumentacja dokera krótko wspomina o 1% zużycia pamięci i 10% spadku wydajności (prawdopodobnie w odniesieniu do operacji alokacji pamięci - tak naprawdę nie określa).
- Cgroup / systemd zostało ostatnio mocno przerobione, więc flux upstream sugeruje, że dostawcy dystrybucji Linuksa mogą poczekać na jego rozstrzygnięcie w pierwszej kolejności.
W CGroup v2 sugerują, że memory.high
powinna to być dobra opcja do ograniczenia przepustowości i zarządzania wykorzystaniem pamięci przez grupę procesów. Jednak ten cytat sugeruje, że monitorowanie sytuacji presji pamięci wymagało więcej pracy (od 2015 r.).
Miara presji pamięci - jak duży wpływ na obciążenie ma brak pamięci - jest niezbędna do ustalenia, czy obciążenie wymaga więcej pamięci; niestety mechanizm monitorowania ciśnienia pamięci nie został jeszcze zaimplementowany.
Biorąc pod uwagę, że narzędzia przestrzeni systemowej i cgroup są złożone, nie znalazłem prostego sposobu, aby ustawić coś odpowiedniego i wykorzystać to dalej. Dokumentacja cgroup i systemd dla Ubuntu nie jest świetna. Przyszłe prace powinny dotyczyć dystrybucji z wydaniami stacjonarnymi, aby wykorzystać grupy i systemd, aby pod wysokim ciśnieniem pamięci ssh i komponenty X-Server / menedżera okien otrzymały wyższy priorytet dostępu do procesora, fizycznej pamięci RAM i IO pamięci, aby uniknąć konkurowania z procesami zajęta zamiana. Funkcje jądra procesora i priorytetowe we / wy istnieją już od jakiegoś czasu. Wydaje się, że jest to priorytetowy dostęp do brakującej fizycznej pamięci RAM.
Jednak nawet priorytety procesora i IO nie są odpowiednio ustawione !? Kiedy sprawdziłem systemowe limity grupy, zastosowane udziały procesora itp., O ile mogłem stwierdzić, Ubuntu nie ustawił żadnych uprzednio zdefiniowanych priorytetów. Np. Prowadziłem:
systemctl show dev-mapper-Ubuntu\x2dswap.swap
Porównałem to z tym samym wyjściem dla ssh, samba, gdm i nginx. Ważne rzeczy, takie jak GUI i zdalna konsola administracyjna, muszą walczyć na równi ze wszystkimi innymi procesami, gdy dochodzi do thrashowania.
Przykładowe limity pamięci, które mam w systemie 16 GB RAM
Chciałem włączyć hibernację, więc potrzebowałem dużej partycji wymiany. Stąd próba złagodzenia za pomocą ulimitów itp.
ulimit
I umieścić * hard as 16777216
w /etc/security/limits.d/mem.conf
taki sposób, że żaden proces nie będą mogły żądać więcej pamięci, niż jest to fizycznie możliwe. Nie będę zapobiegać wyrzucaniu wszystkich razem, ale bez tego tylko jeden proces z chciwym użyciem pamięci lub wyciek pamięci może spowodować wyrzucenie. Np. Widziałem, gnome-contacts
jak zajmowałem ponad 8 GB pamięci podczas robienia przyziemnych czynności, takich jak aktualizowanie globalnej listy adresów z serwera wymiany ...
Jak widać ulimit -S -v
, w wielu dystrybucjach ten twardy i miękki limit jest ustawiony jako „nieograniczony”, teoretycznie proces może skończyć się żądaniem dużej ilości pamięci, ale tylko aktywnie korzystaniem z podzbioru, i działa z radością, myśląc, że otrzymał 24 GB pamięci RAM system ma tylko 16 GB. Powyższy twardy limit spowoduje, że procesy, które mogły działać poprawnie, zostaną przerwane, gdy jądro odmówi ich chciwych spekulacyjnych żądań pamięci.
Jednak łapie również szalone rzeczy, takie jak kontakty gnomów i zamiast stracić czas reakcji pulpitu, pojawia się błąd „niewystarczającej ilości wolnej pamięci”:
Komplikacje ustawiające ulimit dla przestrzeni adresowej (pamięć wirtualna)
Niestety niektórzy programiści lubią udawać, że pamięć wirtualna jest nieskończonym zasobem, a ustawienie limitu pamięci wirtualnej może uszkodzić niektóre aplikacje. Np. WebKit (od którego zależą niektóre aplikacje gnome) dodał funkcję gigacage
bezpieczeństwa, która próbuje przydzielić szaloną ilość pamięci wirtualnej i pojawiają się FATAL: Could not allocate gigacage memory
błędy z podstępną wskazówką Make sure you have not set a virtual memory limit
. Obejście,GIGACAGE_ENABLED=no
rezygnuje z korzyści związanych z bezpieczeństwem, ale podobnie, niedozwolone ograniczenie alokacji pamięci wirtualnej, również rezygnuje z funkcji bezpieczeństwa (np. kontrola zasobów, która może zapobiec odmowie usługi). Jak na ironię, między twórcami gigacage i gnome wydaje się, że zapominają, że samo ograniczenie pamięci to kontrola bezpieczeństwa. I niestety zauważyłem, że aplikacje gnome oparte na gigacage nie zawracają sobie głowy jawnym żądaniem wyższego limitu, więc nawet miękki limit psuje rzeczy w tym przypadku.
Szczerze mówiąc, jeśli jądro lepiej sobie poradzi z możliwością odmowy przydzielenia pamięci na podstawie użycia pamięci rezydentnej zamiast pamięci wirtualnej, udawanie, że pamięć wirtualna jest nieograniczona, byłoby mniej niebezpieczne.
przesada
Jeśli wolisz, aby aplikacje nie miały dostępu do pamięci i chcesz przestać przesadzać, użyj poniższych poleceń, aby sprawdzić, jak zachowuje się twój system pod wysokim ciśnieniem pamięci.
W moim przypadku domyślnym współczynnikiem zatwierdzenia było:
$ sysctl vm.overcommit_ratio
vm.overcommit_ratio = 50
Ale staje się to w pełni skuteczne tylko podczas zmiany zasad, aby wyłączyć nadpisywanie i zastosować współczynnik
sudo sysctl -w vm.overcommit_memory=2
Współczynnik sugerował, że ogólnie można przydzielić tylko 24 GB pamięci (16 GB RAM * 0,5 + 16 GB SWAP). Prawdopodobnie nigdy nie widziałbym, aby OOM się pojawił, i faktycznie mniej prawdopodobne jest, aby procesy stale uzyskiwały dostęp do pamięci podczas wymiany. Ale prawdopodobnie poświęcę też ogólną wydajność systemu.
Spowoduje to awarię wielu aplikacji, zważywszy, że deweloperzy często nie wdzięcznie obsługują system operacyjny, odrzucając żądanie alokacji pamięci. Zapobiega sporadycznemu ryzyku wyciągnięcia blokady z powodu przeładowania (utrata całej pracy po twardym resecie) do częstszego ryzyka awarii różnych aplikacji. W moich testach niewiele to pomogło, ponieważ sam komputer zawiesił się, gdy system był pod presją pamięci i nie mógł przydzielić pamięci. Jednak przynajmniej konsole i SSH nadal działały.
Jak działa pamięć Overcommit VM, ma więcej informacji.
Zdecydowałem się na przywrócenie domyślnych ustawień sudo sysctl -w vm.overcommit_memory=0
, biorąc pod uwagę cały stos graficzny pulpitu i aplikacje w nim występujące.