zapobiec zawieszeniu się systemu / brakowi reakcji z powodu zamiany zużycia pamięci

48

Jeśli proces wymaga dużej ilości pamięci, system przenosi wszystkie inne procesy do pliku wymiany. W tym wydaje się, niezbędne procesy, takie jak serwer X11 lub terminal.

Jeśli więc proces nadal alokuje bez ograniczeń, wszystko przestaje odpowiadać, dopóki ten proces nie zostanie zabity przez zabójcę OOM. Mój laptop wydaje się szczególnie rozsądny i reaguje wyjątkowo źle. Właśnie spędziłem CAŁĄ GODZINĘ, czekając na zakończenie procesu, podczas którego nawet kursor myszy nie może zostać poruszony.

Jak można tego uniknąć?

1) Wyłącz swap => Często uruchamiam wiele procesów, które następnie stają się nieaktywne. Nieaktywne należy przenieść na wymianę.

2) Uzyskaj dysk SSD => za drogi

3) ustaw maksymalną pamięć ulimit =>, ale wtedy się nie powiedzie, gdy program potrzebuje rezonansowej, dużej ilości pamięci. problemem nie jest to, że zużywa za dużo, ale że tłumi inne procesy

4) przechowuj ważne programy (X11, bash, kill, top, ...) w pamięci i nigdy nie zamieniaj tych => czy można to zrobić? w jaki sposób? może zamieniasz tylko duże programy?

5)

BeniBela
źródło
I znowu się powtórzyło :( Uruchomiłem gcc, gdy Firefox był uruchomiony, wszystko było zablokowane na pół godziny. Brak ruchu myszy, brak czytania ebooka
BeniBela
Nie jestem pewien, czy rozumiem, czego chcesz. Czy chcesz, aby system działał magicznie szybciej dzięki posiadanym zasobom? Czy chcesz, aby wcześniej zabijało procesy wykorzystujące dużo pamięci?
David Schwartz
Wygląda na to, że tak naprawdę potrzebujesz więcej pamięci RAM. Lub mniej „nieaktywnych” zadań w tle.
Daniel B,
2
Możesz użyć kombinacji klawiszy Alt + SysRq + F , aby wymusić uruchomienie OOM-killera. Może to skrócić czas niezbędny do oczekiwania na otwarcie konsoli przez system i zabicie procesu.
hololeap
Popraw mnie, jeśli się mylę, ale ten problem faktycznie brzmi, jakby system szuka miejsca wymiany dysku, które powinno istnieć, ale nie istnieje (partycja wymiany jest za mała). Brak wystarczającej ilości miejsca wymiany spowoduje, że system „przebije” dysk twardy (lub ssd) w poszukiwaniu dostępnego miejsca.
mchid

Odpowiedzi:

45

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ą asopcji w limits.conf). Kiedyś działało to wystarczająco dobrze, ale dzięki wprowadzeniu WebKit gigacagewiele 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_ratioale 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, OOMScoreAdjustjest 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:

  • MemoryHigh
  • MemoryMax

Inne przydatne opcje mogą być

  • IOWeight
  • CPUShares

Mają one pewne wady:

  1. 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).
  2. 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.highpowinna 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 16777216w /etc/security/limits.d/mem.conftaki 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-contactsjak zajmowałem ponad 8 GB pamięci podczas robienia przyziemnych czynności, takich jak aktualizowanie globalnej listy adresów z serwera wymiany ...

Kontakty gnomów przeżuwają pamięć RAM

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”:

wprowadź opis zdjęcia tutaj

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ę gigacagebezpieczeństwa, która próbuje przydzielić szaloną ilość pamięci wirtualnej i pojawiają się FATAL: Could not allocate gigacage memorybłędy z podstępną wskazówką Make sure you have not set a virtual memory limit. Obejście,GIGACAGE_ENABLED=norezygnuje 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.

JPvRiel
źródło
3
To najlepszy opis, jaki widziałem na ten temat, i nie uciekaj się do „po prostu kup więcej pamięci RAM!” Jedną z rzeczy, o których nie wspominasz, jest sposób, w jaki grają w to opcje konfiguracji jądra. Na przykład, czy zastosowany model przedwstępny lub program planujący we / wy miałyby jakikolwiek znaczący wpływ na którykolwiek z tych elementów?
hololeap
2
but the kernel won't be able to use an overcommit strategy for allocating memory and this will likely hurt performance. Even a smaller swap partition allows this. Czy jest na to jakiś dowód? Wierzę, że jądro zbyt dobrze się przepełnia bez skonfigurowanej wymiany
ygrek,
@ygrek, dzięki, że sformułowania wyglądają trochę źle - overcommit nadal działa bez zamiany, chyba że zostanie wybrany tryb nigdy nie przepełniania (2). Domyślny heurystyczny tryb nadpisywania (0) lub zawsze zatwierdzania (1) prawdopodobnie nadal działa bez zamiany. Nie mogę sobie przypomnieć, gdzie czytałem, że wyłączenie swap szkodzi zdolności nadmiernie zaangażowanego kodu do alokacji pamięci (i na który tryb miał konkretny wpływ). Znów googlowałem bez powodzenia, ale to był półprzydatny post: stackoverflow.com/questions/38688824/ ... Odpowiem odpowiednio zmienię.
JPvRiel,
Miałem nadzieję, że łatka do zapisu w tle pomoże mi, ale korzystam z bardzo nowego jądra (4.14.81) i napotykam poważne problemy z odpowiedzią przy dużym obciążeniu dysku-we / wy (niezależnie od tego, czy przyczyną jest zamiana). Zastanawiam się, czy menedżer urządzeń lub moje szyfrowanie LUKS powodują problemy z wydajnością. Naprawdę nie mam pojęcia, jak rozwiązać ten problem.
Darius Jahandarie