Zabójca OOM w Linuksie sieją spustoszenie w różnych aplikacjach co jakiś czas i wydaje się, że tak naprawdę niewiele robi się po stronie programistycznej jądra, aby to poprawić. Czy nie byłoby lepiej, jako najlepszą praktykę podczas konfigurowania nowego serwera , odwrócić domyślną pamięć nadmiarową pamięci, to znaczy wyłączyć ją ( vm.overcommit_memory=2
), chyba że wiesz, że chcesz ją włączyć do określonego zastosowania? A jakie byłyby te przypadki użycia, w których wiesz, że chcesz przesadzać?
Jako bonus, skoro zachowanie w przypadku vm.overcommit_memory=2
zależy od vm.overcommit_ratio
i zamiany przestrzeni, jaka byłaby dobra zasada przy doborze tych dwóch ostatnich, aby cała konfiguracja działała rozsądnie?
Zabójca OOM sieje spustoszenie tylko wtedy, gdy przeciąłeś swój system. Daj mu wystarczająco dużo zamiany i nie uruchamiaj aplikacji, które nagle decydują się zjeść ogromne ilości pamięci RAM, a nie będziesz mieć problemu.
Aby dokładnie odpowiedzieć na twoje pytania:
brk
(2) (a opakowania, które ich używają, takie jakmalloc
(3)) zwracają błąd. Kiedy eksperymentowałem z tym w mojej poprzedniej pracy, uważałem, że trudniej jest uzyskać wszystko, co jest w stanie poradzić sobie z błędami braku pamięci, niż po prostu poradzić sobie z konsekwencjami OOM (które w naszym przypadku było o wiele gorsze niż konieczność restartowania okazjonalnej usługi, jeśli wystąpiła OOM - musieliśmy zrestartować cały klaster, ponieważ GFS jest parą kału).Zasadniczo z mojego doświadczenia wynika, że wyłączenie nadmiernego zaangażowania jest fajnym eksperymentem, który rzadko sprawdza się w praktyce tak, jak brzmi teoretycznie. To ładnie koresponduje z moimi doświadczeniami z innymi tuningami w jądrze - programiści jądra Linuksa są prawie zawsze mądrzejsi od ciebie, a domyślne ustawienia działają najlepiej w ogromnej większości przypadków. Zostaw je w spokoju, a zamiast tego znajdź proces powodujący wyciek i napraw go.
źródło
Hmm, nie przekonują mnie argumenty przemawiające za przesadnym zabójstwem OOM ... Kiedy pisze Womble,
„Zabójca OOM sieje spustoszenie tylko wtedy, gdy przeciążiłeś swój system. Daj mu dość zamiany i nie uruchamiaj aplikacji, które nagle zdecydują się zjeść ogromne ilości pamięci RAM, i nie będziesz mieć problemu”.
Opisuje scenariusz środowiskowy, w którym nadmierne zaangażowanie i zabójca OOM nie są wymuszane lub nie działają „tak naprawdę” (jeśli wszystkie aplikacje przydzielą pamięć w razie potrzeby i będzie wystarczająca ilość pamięci wirtualnej do przydzielenia, zapisy pamięci będą ściśle zgodne z przydzieleniem pamięci bez błędy, więc tak naprawdę nie moglibyśmy mówić o zbyt dużym systemie, nawet gdyby włączona była strategia nadmiernego zaangażowania). Chodzi o ukryte przyznanie, że przesadne zabójstwo i zabójca OOM działają najlepiej, gdy ich interwencja nie jest potrzebna, co w pewnym stopniu podziela większość zwolenników tej strategii, o ile mogę powiedzieć (i przyznaję, że nie mogę powiedzieć wiele ...). Co więcej, odnosząc się do aplikacji o określonych zachowaniach podczas wstępnej alokacji pamięci, myślę, że konkretna obsługa może być dostrojona na poziomie dystrybucji, zamiast mieć wartość domyślną,
Jeśli chodzi o JVM, to jest to maszyna wirtualna, do pewnego stopnia musi przydzielić wszystkie zasoby, których potrzebuje podczas uruchamiania, aby mogła stworzyć swoje „fałszywe” środowisko dla swoich aplikacji i trzymać swój wolny zasób oddzielony od hosta środowisko, w miarę możliwości. Dlatego może być bardziej pożądane, aby nie uruchamiał się podczas uruchamiania, zamiast po pewnym czasie w wyniku „zewnętrznego” stanu OOM (spowodowanego nadmiernym zaangażowaniem / zabójcą OOM / cokolwiek) lub w każdym razie cierpienia z powodu takiego stanu zakłócającego jego własny wewnętrzne strategie obsługi OOM (ogólnie rzecz biorąc, maszyna wirtualna powinna uzyskać wszelkie wymagane zasoby od początku, a system hosta powinien je „ignorować” do końca, w ten sam sposób, w jaki jakakolwiek ilość fizycznego RAM udostępnionego z kartą graficzną nigdy nie jest - i nie może być - dotknięty przez system operacyjny).
Jeśli chodzi o Apache, wątpię, aby od czasu do czasu zabić cały serwer i zrestartować go lepiej, niż pozwolić jednemu dziecku, wraz z jednym połączeniem, zawieść od początku (= dziecka / połączenia) na początku (jakby to była zupełnie nowa instancja JVM utworzony po uruchomieniu innej instancji przez chwilę). Myślę, że najlepsze „rozwiązanie” może zależeć od konkretnego kontekstu. Na przykład, biorąc pod uwagę usługę e-commerce, może być o wiele lepszym rozwiązaniem, aby czasami kilka losowych połączeń z planem zakupów zawodziło losowo zamiast tracić całą usługę, z ryzykiem, na przykład, zakłócenia trwającej finalizacji zamówienia lub (może gorzej) proces płatności ze wszystkimi konsekwencjami sprawy (może nieszkodliwy, ale może szkodliwy - i na pewno, gdy pojawią się problemy,
W ten sam sposób, na stacji roboczej proces, który zużywa najwięcej zasobów, a więc dostosowywanie go jako pierwszego wyboru dla zabójcy OOM, może być aplikacją wymagającą dużej ilości pamięci, taką jak transkoder wideo lub oprogramowanie do renderowania, prawdopodobnie jedyną aplikacją użytkownik chce pozostać nietknięty. Te rozważania podpowiadają mi, że domyślna polityka zabójcy OOM jest zbyt agresywna. Wykorzystuje podejście „najgorszego dopasowania”, które jest w pewnym stopniu podobne do niektórych systemów plików (OOMK próbuje zwolnić jak najwięcej pamięci, jednocześnie zmniejszając liczbę zabitych podprocesów, aby zapobiec dalszej interwencji w krótkim czasie, ponieważ a także fs może przydzielić więcej miejsca na dysku, niż jest faktycznie potrzebne dla określonego pliku, aby zapobiec dalszemu przydziałowi, jeśli plik się powiększy, a tym samym do pewnego stopnia zapobiec fragmentacji).
Uważam jednak, że polityka przeciwna, na przykład podejście „najlepiej dopasowane”, może być lepsza, aby w pewnym momencie uwolnić potrzebną dokładną pamięć i nie zawracać sobie głowy „dużymi” procesami, które mogą być marnotrawstwem pamięć, ale także może nie, a jądro nie może tego wiedzieć (hmm, mogę sobie wyobrazić, że śledzenie liczby dostępów do stron i czasu może wskazywać, że proces alokuje pamięć, nie potrzebuje więcej, więc zgadnij, czy proces marnuje pamięć lub po prostu dużo zużywa, ale opóźnienia dostępu powinny być ważone w cyklach procesora, aby odróżnić marnowanie pamięci od aplikacji intensywnie korzystającej z pamięci i procesora, ale, chociaż potencjalnie niedokładna, taka heurystyka może mieć nadmierny narzut).
Co więcej, może nie być prawdą, że zabicie mniejszej liczby możliwych procesów jest zawsze dobrym wyborem. Na przykład w środowisku komputerowym (na przykład nettop lub netbook z ograniczonymi zasobami, na przykład) użytkownik może uruchamiać przeglądarkę z kilkoma kartami (w ten sposób zużywając pamięć - załóżmy, że jest to pierwszy wybór dla OOMK) , a także kilka innych aplikacji (edytor tekstu z niezapisanymi danymi, klient poczty, czytnik pdf, odtwarzacz multimediów, ...) oraz kilka demonów (systemowych), a także kilka instancji menedżera plików. Teraz pojawia się błąd OOM i OOMK decyduje się zabić przeglądarkę, gdy użytkownik robi coś, co uznaje się za „ważne” w sieci ... użytkownik byłby rozczarowany. Z drugiej strony zamknięcie kilku menedżerów plików
W każdym razie uważam, że użytkownik powinien mieć możliwość samodzielnego podjęcia decyzji o tym, co należy zrobić. W systemie stacjonarnym (= interaktywnym) powinno to być względnie łatwe, pod warunkiem, że zarezerwowano wystarczającą ilość zasobów, aby poprosić użytkownika o zamknięcie dowolnej aplikacji (ale wystarczy nawet zamknięcie kilku kart) i obsłużenie jego wyboru (opcja może polega na utworzeniu dodatkowego pliku wymiany, jeśli jest wystarczająco dużo miejsca). W przypadku usług (i ogólnie) rozważę również dwa dalsze możliwe ulepszenia: jeden rejestruje interwencje zabójcy OOM, a także procesy uruchamiania / rozwidlania awarii w taki sposób, że awaria może być łatwo debugowana (na przykład interfejs API może poinformować proces, który wydał utworzenie nowego procesu lub rozwidlenie - dlatego serwer taki jak Apache, z odpowiednią poprawką, może zapewnić lepsze rejestrowanie niektórych błędów); można tego dokonać niezależnie od wysiłku nadmiernego zaangażowania / OOMK; po drugie, ale nie ważne, można ustanowić mechanizm dostrajania algorytmu OOMK - wiem, że jest możliwe, do pewnego stopnia, zdefiniowanie konkretnej polityki dla poszczególnych procesów, ale chciałbym „scentralizowany” mechanizm konfiguracji oparty na jednej lub większej liczbie list nazw aplikacji (lub identyfikatorów) w celu zidentyfikowania odpowiednich procesów i nadania im pewnego stopnia ważności (zgodnie z wymienionymi atrybutami); taki mechanizm powinien (lub przynajmniej mógłby) być również warstwowy, tak aby istniała lista zdefiniowana przez użytkownika najwyższego poziomu, lista zdefiniowana przez system (dystrybucję) oraz wpisy zdefiniowane przez aplikację (na najniższym poziomie) , na przykład menedżer plików DE może poinstruować OOMK, aby bezpiecznie zabił dowolną instancję,
Ponadto można zapewnić interfejs API, aby umożliwić aplikacjom zwiększenie lub obniżenie poziomu „ważności” w czasie wykonywania (w odniesieniu do celów zarządzania pamięcią i niezależnie od priorytetu wykonania), aby na przykład procesor tekstu mógł zacząć małe „znaczenie”, ale wzrasta, gdy niektóre dane są przechowywane przed opróżnieniem do pliku lub wykonywana jest operacja zapisu, a mniejsza ważność ponownie, gdy taka operacja się skończy (analogicznie menedżer plików może zmienić poziom, gdy przejdzie z tylko udostępnianie plików do obsługi danych i odwrotnie, zamiast używania osobnych procesów, a Apache może nadać różny poziom ważności różnym dzieciom lub zmienić stan dziecka zgodnie z niektórymi zasadami ustalonymi przez sysadmins i ujawnionymi przez Apache - lub dowolny inny serwer - ustawienia). Oczywiście, taki interfejs API mógłby i byłby nadużywany / nadużywany, ale myślę, że jest to niewielki problem w porównaniu do jądra arbitralnie zabijającego procesy w celu zwolnienia pamięci bez żadnych istotnych informacji o tym, co dzieje się w systemie (oraz o zużyciu pamięci / czasie tworzenia lub podobnych) dla mnie wystarczające lub „sprawdzające”) - tylko użytkownicy, administratorzy i autorzy programów mogą naprawdę ustalić, czy proces jest „nadal potrzebny” z jakiegoś powodu, jaki jest powód i / lub czy aplikacja jest w stanie wiodącym do utraty danych lub innych szkód / problemów w przypadku śmierci; można jednak poczynić pewne założenia, na przykład szukać zasobów pewnego rodzaju (deskryptory plików, gniazda sieciowe itp.) pozyskanych przez proces, a przy oczekujących operacjach można stwierdzić, czy proces powinien być w wyższym „stanie” niż jeden zestaw,
Lub po prostu unikaj nadmiernego zaangażowania i pozwól jądru robić to, co musi zrobić jądro, przydzielając zasoby (ale nie ratując ich arbitralnie jak zabójca OOM), planując procesy, zapobiegając głodom i impasom (lub ratując przed nimi), zapewniając pełne zapobieganie i separacja przestrzeni pamięci i tak dalej ...
Chciałbym również poświęcić więcej słów na temat przesadnych podejść. Z innych dyskusji pomyślałem, że jedną z głównych obaw związanych z nadmiernym zaangażowaniem (zarówno jako powód, aby tego chcieć, jak i jako źródło możliwych problemów) jest obsługa rozwidlenia: szczerze mówiąc, nie wiem, jak dokładnie kopia- Strategia zapisu jest zaimplementowana, ale myślę, że każdą agresywną (lub optymistyczną) politykę można złagodzić dzięki strategii podobnej do zamiany. Oznacza to, że zamiast klonować (i dostosowywać) rozwidlone strony kodowe procesu i struktury planowania, kilka innych stron danych można skopiować przed faktycznym zapisem, wybierając spośród tych stron, do których proces macierzysty uzyskiwał częstsze zapisywanie (to znaczy za pomocą licznika do operacji zapisu).
Wszystko oczywiście IMHO.
źródło
/proc/$PID/oom_adj
./proc/$PID/oom_score_adj
Credit: - Jądro Linux uruchamia zabójcę OOM
źródło