Fragmentacja pamięci podczas pracy serwera oznacza, że duże, ciągłe bloki nie są już dostępne pomimo wolnej pamięci RAM, a krytyczne alokacje kończą się niepowodzeniem. Przedstawiam przyczyny, typowe objawy i ukierunkowane środki zaradcze, aby Serwer reagują w sposób obliczalny, a alokacje mogą być wiarygodnie funkcja.
Punkty centralne
- Wewnętrzny oraz zewnętrzny Rozróżnienie i konkretne zajęcie się fragmentacją.
- Kolega-alokator zrozumieć: Zamówienia, podziały, brakujące scalenia.
- Narciarz biegowy-Prawidłowe ustawienie obciążeń, narzutu hiperwizora i THP.
- Diagnoza z buddyinfo, vmstat i metrykami zagęszczania.
- Wzorzec alokacji poprawić: Pule, wstępna alokacja, oddzielne okresy życia.
Co oznacza fragmentacja pamięci w codziennym użytkowaniu serwera?
określam jako Pamięć Fragmentacja to stan, w którym wolna pamięć robocza rozpada się na wiele małych luk, a duże żądania nie otrzymują już ciągłego obszaru. Fragmentacja wewnętrzna występuje, gdy przydzielony blok jest większy niż rzeczywiste zapotrzebowanie, a niewykorzystane bajty pozostają w bloku, co może prowadzić do Wydajność jest zmniejszona. Zewnętrzna fragmentacja występuje, gdy wolne sekcje są dystrybuowane i nie łączą się już w duży obszar, nawet jeśli ogólnie jest wystarczająco dużo wolnej pamięci RAM. To właśnie w tym przypadku duże bufory, rezerwacje JIT lub sterowniki, które preferują ciągłą pamięć, zawodzą z powodu pozornie paradoksalnego niedoboru dużych bloków. W środowiskach hostingowych, wysokie obciążenia równoległe, długie czasy pracy i heterogeniczne stosy oprogramowania zaostrzają ten problem. Dynamika zauważalne.
Jak Linux-Buddy-Allocator tworzy fragmentację
Jądro Linux zarządza pamięcią fizyczną za pomocą funkcji Kumpel-allocator, który organizuje strony w klasy wielkości (zamówienia), zaczynając od 4 KB. Jeśli procesy zażądają większych obszarów, jądro dzieli duże bloki na bloki, dopóki nie będzie dostępny odpowiedni rozmiar; po zwolnieniu próbuje ponownie połączyć bloki. Jednak różne długości żądań, zmieniające się czasy życia i nierównomierne zwalnianie uniemożliwiają ponowne łączenie i zachęcają do korzystania z zewnętrznych źródeł. Fragmentacja. Z biegiem czasu zapasy dużych zamówień opróżniają się, podczas gdy małe zamówienia pęcznieją - /proc/buddyinfo pokazuje wtedy wysokie liczby w niskich zamówieniach i zera w wysokich zamówieniach. Od tego momentu zagęszczanie i prawdopodobnie zachowanie OOM interweniują częściej, co powoduje opóźnienia i zwiększa zakłócenia.
Przyczyny w środowiskach hostingu i wirtualizacji
Długotrwałe obciążenia sieciowe i bazodanowe tworzą zmienny wzorzec alokacji, który rozbija duże bloki i umożliwia późniejsze Połączenie zapobiegać. Frameworki i biblioteki, które zwalniają pamięć z opóźnieniem lub w nieskoordynowany sposób, pozostawiają luki, w których można uwzględnić tylko małe żądania. Wirtualizacja dodaje swój własny narzut i przenosi alokacje na gościa i hiperwizora, co oznacza, że zewnętrzny Fragmentacja jest tworzony szybciej. Nieprawidłowo ustawione wartości vm.min_free_kbytes zwiększają presję, ponieważ jądro ma zbyt mało buforów na alokacje atomowe lub nadmiernie je rezerwuje. Więcej przejrzystości na temat Pamięć wirtualna pomaga mi uporządkować interakcję między alokatorem gości, THP, Huge Pages i hypervisorem.
Wpływ na wydajność i wrażenia użytkownika
Jeśli zbiornik jest podzielony na wiele małych wysp, to Opóźnienia, ponieważ jądro kompresuje i zmienia się częściej, zanim będzie w stanie obsłużyć duże żądania. Aplikacje, które wymagają ciągłych obszarów - takich jak bazy danych, pamięci podręczne lub potoki multimedialne - działają szybciej. Pomimo „wolnej“ pamięci RAM, duże alokacje kończą się niepowodzeniem i generują komunikaty o błędach, restarty lub twarde anulowania, co może powodować sesje i Transakcje osłabione. Działania w tle, takie jak zagęszczanie, zwiększają obciążenie procesora i obciążenie we/wy, sprawiając, że nawet lekkie obciążenia wydają się wolniejsze. W scenariuszach hostingowych objawia się to długimi czasami odpowiedzi, sporadycznymi przekroczeniami limitu czasu i gorszym skalowaniem podczas szczytowych obciążeń.
Diagnostyka: od buddyinfo do metryk zagęszczania
Najpierw sprawdzam /proc/buddyinfo, aby zobaczyć, który Zamówienia vmstat i sar pokazują, jak często jądro kompaktuje lub czy ścieżka OOM stała się aktywna, co wskazuje na presję ze strony dużych alokacji. Używam perf i strace, aby rozpoznać, czy wątki czekają na bezpośrednie zagęszczenie, a zatem czasy odpowiedzi wahają się, co jest zauważalne w dziennikach i metrykach. W środowiskach z serwerami Windows wizualizuję pofragmentowane sterty za pomocą narzędzi do debugowania, aby sprawdzić duże luki i dostroić parametry sterty. dostosowanie. Mierzę również największy wolny blok, ponieważ suma wolnej pamięci RAM nie jest wystarczająca jako diagnoza.
Tuning jądra i maszyny wirtualnej w praktyce
Ustawiam vm.min_free_kbytes na umiarkowanie wyższym poziomie, często w przedziale 5-10 % pamięci RAM, tak aby jądro miało duże, atomowe zasoby. Zapytania mogą być obsługiwane niezawodnie. Przezroczyste ogromne strony aktywuję ostrożnie: albo na żądanie, albo przez madvise, w zależności od profilu obciążenia i ryzyka fragmentacji. Statyczne ogromne strony oferują przewidywalność, ale wymagają odpowiedniego planowania, aby nie powodować problemów w innych miejscach. Wąskie gardła aby stworzyć porządek. Zagęszczanie wyzwala porządek w krótkim okresie, ale nie zastępuje strukturalnego rozwiązania dla trwałych, niestabilnych wzorców. Uwzględniam topologie NUMA w strojeniu, aby duże alokacje pozostały lokalne i nie strzępiły się między węzłami.
| Ustawienie | Cel | Korzyści | Wskazówka |
|---|---|---|---|
| vm.min_free_kbytes | Rezerwa na duże alokacje | Mniej szczytów OOM/zagęszczeń | Stopniowe zwiększanie i mierzenie wartości |
| THP (on/madvise) | Preferowanie większych stron | Mniejsza fragmentacja, lepszy wskaźnik TLB | Zwróć uwagę na opóźnienia obciążenia |
| Ogromne strony (statyczny) | Rezerwowe obszary ciągłe | Przewidywalne duże bloki | Planowanie wydajności z wyprzedzeniem |
| Zagęszczanie | Łączenie wolnych obszarów | Tymczasowo większe bloki | Zwiększa CPU/I&O w krótkim okresie czasu |
| NUMA-Polityka | Bezpieczna alokacja lokalna | Niższe opóźnienia, mniejszy ruch krzyżowy | Konfiguracja równoważenia |
Strefy przechowywania, typy migracji i dlaczego „nieruchome“ blokują wszystko
Alokator stron działa nie tylko z poleceniami, ale także z Strefy (DMA, DMA32, Normalny, Ruchomy) i Migracja typów (RUCHOME, NIERUCHOME, ODZYSKIWALNE). Granulki do tego celu to „pageblocks“. Gdy tylko NIEPRZENOŚNE strony (np. struktury jądra, strony przypięte przez sterowniki) dostaną się do pageblocka, jądro oznacza ten blok jako trudny do przeniesienia. To właśnie te „zanieczyszczone“ bloki uniemożliwiają Compaction łączenie wolnych obszarów w duże, ciągłe obszary. Obszary formularzy. Dlatego świadomie planuję pojemność w ZONE_MOVABLE (tam, gdzie to możliwe) i upewniam się, że dane aplikacji są przydzielane głównie jako MOVABLE. Oznacza to, że duże, ciągłe rezerwy są bardziej dostępne. W przypadku obciążeń o wysokich wymaganiach DMA używam ukierunkowanych rezerwacji, aby strony UNMOVABLE nie niszczyły szerokiej strefy normalnej.
Czysty wzór alokacji
Grupuję wymagania dotyczące przechowywania według ŻywotnośćObiekty krótkotrwałe w pulach, obiekty długotrwałe w oddzielnych regionach, aby wydania nie niszczyły wszystkiego na całej planszy. Często występujące rozmiary grupuję w stałych pulach, aby zmniejszyć fluktuację zamówień i odciążyć alokator. Wstępnie planuję duże bufory na początku, zamiast żądać ich w środku ruchu, co pozwala uniknąć szczytów obciążenia podczas łączenia. Dostosowuję żądania wyrównania do rzeczywistych potrzeb, ponieważ nadmierne wyrównania marnują miejsce i zachęcają do wewnętrznych zmian. Fragmentacja. W potokach kompilacji i wdrażania testuję ścieżki pamięci masowej za pomocą scenariuszy obciążenia, zanim ruch zostanie uruchomiony.
Wybór alokatora w przestrzeni użytkownika: glibc, jemalloc, tcmalloc
Nie każda fragmentacja jest problemem jądra. The Przestrzeń użytkownika-Alokator ma duży wpływ na wzorzec, który alokator kumpla widzi na końcu. glibc malloc używa aren na wątek; na wielu rdzeniach może to prowadzić do dużej wewnętrznej fragmentacji. Ograniczam liczbę aren i przycinam je bardziej agresywnie, aby nieużywane obszary szybciej wracały do systemu operacyjnego. Alternatywy takie jak jemalloc lub tcmalloc oferują drobniejsze klasy wielkości i bardziej spójne wzorce współdzielenia, co może zauważalnie zmniejszyć fragmentację zewnętrzną. Decydującym czynnikiem jest: Mierzę pod obciążeniem produkcyjnym, ponieważ każdy alokator ma różne kompromisy w zakresie opóźnień, przepustowości i śladu pamięci. W przypadku usług o wysokiej przepustowości i jednolitych rozmiarach obiektów, dedykowane areny lub pule przypominające płyty często zapewniają najbardziej stabilną wydajność. Opóźnienia.
Środki po stronie aplikacji: Java, PHP, pamięci podręczne i bazy danych
W Javie używam Areny lub alokator regionu i wybrać profile GC, które faworyzują duże, ciągłe rezerwacje zamiast ciągłego rozbijania sterty na drobne kawałki. Równoważę Xms/Xmx tak, aby sterta nie rosła i nie kurczyła się, ponieważ takie pompowanie sprzyja powstawaniu dziur. W przypadku stosów PHP i MySQL używam stałych pul pamięci, ograniczam zbyt duże obiekty i optymalizuję rozmiary buforów w celu uzyskania spójnych wzorców alokacji. Optymalizacja PHP/MySQL. Organizuję systemy buforowania (np. bufory obiektów lub stron) dla jednolitych rozmiarów fragmentów, aby wydania nie pozostawiały dużych luk. Jeśli nic innego nie pomaga, planuję kontrolowane restarty w oknach konserwacyjnych, zamiast ryzykować nieplanowane zdarzenia OOM, które mogą spowodować awarię całego systemu. Usługi aby anulować.
Praktyka w zakresie kontenerów i Kubernetes
Kontenery nie zmieniają funkcjonalności aplikacji Kumpel-Alokatory - segmentują tylko widoki i limity. Fragmentacja pozostaje zatem kwestią hosta, ale przejawia się w strąkach poprzez eksmisje, wahania opóźnień lub koszty podziału THP. Osiągam stabilność poprzez:
- Ustaw klasy QoS (Guaranteed/Burstable) tak, aby krytyczne pody otrzymywały stałe rezerwy i nie rosły i nie kurczyły się w tym samym czasie.
- limity pamięci realistycznie, tak aby przycinanie i odzyskiwanie nie naruszały stale twardych limitów pamięci. Granice zderzają się.
- THP/Hugepages konsekwentnie obejmują cały host i zapewniają zasobnikom, które potrzebują dużych stron, statycznie zarezerwowane pule.
- Używaj strategii rozgrzewania (przed awarią, przed alokacją), aby duże bloki były zajmowane wcześnie i nie były później wymagane pod obciążeniem.
Monitoruje skonteneryzowane węzły jak goły metal: buddyinfo, zdarzenia zagęszczania, zabójstwa OOM - tylko koreluję również z restartami podów i eksmisjami, aby czysto oddzielić przyczynę.
Wirtualizacja, NUMA i wpływ sprzętu
Wśród hiperwizorów sprawdzam, jak alokator gościa, balonowanie i THP hosta współdziałają ze sobą, ponieważ nakładanie warstw może zwiększać fragmentację i tworzyć duże Bloki czyni go rzadkim. Konsekwentnie obserwuję topologie NUMA: lokalna alokacja zmniejsza opóźnienia i zapobiega rozproszeniu dużych żądań na węzły, a tym samym ich zmniejszeniu. Tam, gdzie ma to sens, przypinam obciążenia do węzłów NUMA i obserwuję wpływ na błędy stron i trafienia TLB. Aby uzyskać dokładniejszą kontrolę, ustawiam wytyczne dla węzłów pamięci masowej i wyciągam Równoważenie NUMA w ukierunkowany sposób. Uwzględniam również aktualizacje oprogramowania układowego i mikrokodu, dzięki czemu mogę wykluczyć nieoczekiwane skutki uboczne i zapewnić przewidywalność w przypadku dużych aplikacji. Wymagania otrzymać.
Sterownik urządzenia, DMA i CMA
Kierowcy, którzy są fizycznie spójny obszary (np. niektóre silniki DMA, multimedia, karty przechwytujące) zaostrzają fragmentację zewnętrzną. Tutaj planuję użyć alokatora pamięci ciągłej (CMA) lub zarezerwować duże bloki na początku procesu rozruchu. Zapobiega to „gryzieniu“ przestrzeni adresowej przez wiele małych alokacji, zanim sterownik otrzyma swoje bufory. Jednocześnie izoluję przypięte strony (np. za pomocą RDMA/DPDK) od ogólnej pamięci aplikacji, aby ich charakter UNMOVABLE nie powodował bezużyteczności całych pageblocków. Powinienem również sprawdzić, czy konfiguracje IOMMU wystarczająco wirtualizują większe, nieciągłe obszary - w przeciwnym razie potrzebuję konkretnych rezerw i wyraźnych limitów czasowych. Windows dla tych alokacji.
Rutyna operacyjna: inteligentne wykorzystanie okien monitorowania i konserwacji
Osadzam migawki buddyinfo, liczniki zagęszczania i zdarzenia OOM w moim Monitoring, aby zobaczyć trendy zamiast pojedynczych zdarzeń. Ograniczam wdrożenia kroczące, aby wahania pamięci koncentrowały się w oknach czasowych, a reszta tygodnia przebiegała płynniej. Podczas okien konserwacyjnych w razie potrzeby ręcznie uruchamiam zagęszczanie, czyszczę pamięć podręczną i ponownie uruchamiam usługi, zanim fragmentacja spowoduje ból produkcyjny. Koreluję dzienniki i metryki ze szczytowym ruchem, aby rozpoznać powtarzające się wzorce i odpowiednio dostosować bufory. W przypadku większych zmian najpierw testuję je w wersji testowej, aby nie odkryć żadnych zaskakujących zmian. Efekty uboczne podczas pracy na żywo.
Runbook: Gdy duże alokacje dziś zawodzą
Jeśli pojawiają się ostre komunikaty o błędach „alokacja zamówienia X nie powiodła się“, pracuję w jasnych krokach:
- Obraz sytuacji: Zapisz buddyinfo, sprawdź vmstat (allocstall/compact), przeszukaj dmesg pod kątem wpisów Compaction/OOM. Oszacuj największy wolny blok (najwyższy rząd z >0).
- Krótkoterminowa ulga: Wstrzymanie niekrytycznych usług, ograniczenie obciążenia, wyczyszczenie pamięci podręcznej w ukierunkowany sposób. Ręczne wyzwalanie zagęszczania i tymczasowa dezaktywacja THP Defrag, jeśli obecnie powoduje szkody.
- Odprawa celowa: Odbudowa dużych, ciągłych buforów w określonych usługach (kontrolowany restart) przed wystąpieniem następnego szczytu.
- Zwiększenie rezerwy: vm.min_free_kbytes i znak wodny ostrożnie, aby zabezpieczyć alokacje atomowe na kilka następnych godzin; efekty ścisłe monitor.
- Stały środek zaradczy: Popraw wzorce alokacji, wprowadź pule, przenieś wstępną alokację na początek, sprawdź lokalizację NUMA i odpowiednio dostosuj THP/Huge Pages.
Mierzone zmienne, SLO i alarmy
Nie tylko mierzę sumy pamięci RAM, ale także definiuję SLO dla alokowalności: „najwyższa kolejność z dostępnością“, „czas do udanej dużej alokacji“, „procent przeciągnięcia zagęszczania“. Na tej podstawie wyprowadzam alarmy, które uderzają wcześnie, zanim użytkownicy zobaczą limity czasu. Przydatne kluczowe liczby obejmują
- Liczba wolnych bloków wysokiego rzędu (np. ≥ rząd 9) na minutę.
- Częstotliwość i czas trwania bezpośredniego zagęszczania lub czas oczekiwania na odzysk.
- Proporcja przypiętych/nieprzypiętych stron w stosunku do całkowitej pamięci.
- Wskaźnik powodzenia dużych alokacji w testach obciążeniowych i po wdrożeniach.
Łączę te metryki z czasami wydań, szczytami ruchu i zmianami konfiguracji. W ten sposób rozpoznaję wzorce, na podstawie których mogę proaktywnie skala lub zmienić harmonogram okna przydziału.
Planowanie wydajności i świadomość kosztów
Obliczam marże magazynowe w taki sposób, że zarówno Normalne działanie a fazy konserwacji ze zwiększonymi alokacjami są odpowiednio uwzględnione. Zamiast modernizować cały system, najpierw sprawdzam przykładowe poprawki, ponieważ dobre dostrojenie często przynosi więcej niż dodatkowa pamięć RAM. Kiedy zwiększam pojemność, planuję rezerwy dla THP/dużych stron, aby duże strony nie kolidowały ze szczytami aplikacji. Konsolidacja na mniejszej liczbie, ale bardziej wydajnych hostów może zmniejszyć fragmentację, pod warunkiem, że odpowiednio ustawię NUMA i profile alokacji. Podsumowując, zmniejszając fragmentację, oszczędzam koszty w euro, ponieważ zmniejszam szczyty CPU i przeciążenia we/wy oraz wydajniej wykorzystuję licencje. użycie.
Krótkie podsumowanie
Fragmentacja pamięci występuje, gdy wiele alokacji o różnych długościach i rozmiarach jest ze sobą połączonych. Obszary a duże zapytania później spełzają na niczym. Rozwiązuję problem na trzech frontach: Kernel/VM tuning (vm.min_free_kbytes, THP/Huge Pages), lepsze wzorce alokacji (pools, pre-allocation, separate lifetimes) i czyste zarządzanie operacjami (monitoring, scheduled pruning, NUMA discipline). Polegam na /proc/buddyinfo, licznikach zagęszczania i pomiarze największego wolnego bloku do diagnostyki, ponieważ sumy czystej pamięci RAM są zwodnicze. Zwracam szczególną uwagę na wirtualizację i hiperwizory, aby gość i host nie działały przeciwko sobie, a duże bloki pamięci RAM nie działały przeciwko sobie. Bloki zarezerwowane na wczesnym etapie. Połączenie tych bloków konstrukcyjnych zwiększa przewidywalność, zapobiega awariom z powodu OOM i zapewnia szybsze reakcje - zwłaszcza gdy ruch i dane rosną.


