...

Analiza i optymalizacja wykorzystania SoftIRQ w systemie Linux

Pokażę krok po kroku, jak Linux SoftIRQ-mierzę obciążenie, uwidaczniaję wąskie gardła i odzyskuję kontrolę dzięki kilku zmianom w jądrze systemu. Przy tym stawiam na wymierne efekty: krótsze Opóźnienia, zrównoważone rdzenie procesora oraz stabilne przetwarzanie pakietów przy dużym obciążeniu sieci.

Punkty centralne

  • Punkty pomiarowe zrozumieć: /proc/softirqs, softnet_stat, interrupts
  • Objawy wykrywanie: obciążenie ksoftirqd, utrata pakietów, skoki opóźnień
  • Strojenie parametry sterujące: netdev_budget i netdev_budget_usecs
  • Dystrybucja zapisz: przypisanie IRQ, RSS, mapowanie kolejek
  • Monitoring przeprowadzić: mpstat, perf, śledzenie

Przegląd SoftIRQ: jak działa jądro

Po wystąpieniu przerwania sprzętowego jądro przenosi część zadań do tzw. SoftIRQs, aby ścieżki krytyczne były szybko zwalniane, a realizacja zadań pozostawała przewidywalna. Zwłaszcza w ścieżce sieciowej moduły obsługi NAPI zbierają pakiety z pierścieni kart sieciowych, inicjują operacje protokołowe i przekazują dane do Stos sieciowy. Gdy liczba zdarzeń wzrasta, wkraczają wątki na procesor, takie jak ksoftirqd/cpuN, i przejmują odpytywanie oraz przetwarzanie zaległe. To oddzielenie poprawia ogólną przepustowość, ale w przypadku przeciążenia może powodować długi czas działania SoftIRQ na poszczególnych Rdzenie prowadzić. Dlatego już na wczesnym etapie obserwuję, czy ścieżki NET_RX i NET_TX dominują oraz czy proces ksoftirqd wyraźnie pochłania czas procesora. W ten sposób rozpoznaję, kiedy softIRQ stają się wąskim gardłem i podejmuję dalsze Optymalizacje są konieczne.

Rozpoznawanie typowych objawów dużego obciążenia SoftIRQ

Wyraźne obciążenie SoftIRQ dostrzegam przede wszystkim po stale wysokim Procesor jądra oraz procesy ksoftirqd, które utrzymują szczytowe wartości przez wiele sekund. Równolegle rosną opóźnienia w operacjach sieciowych i blokowych wejścia/wyjścia, co przejawia się w powolnych uzgodnieniach TLS lub spowolnionych Interfejsy API wyraża. Często dochodzi do utraty pakietów, podczas gdy pierścienie karty sieciowej ulegają przepełnieniu, a zaległości rosną. Gdy przerwy są źle rozdzielone, procesor 0 często bardzo na tym cierpi, ponieważ wiele linii IRQ wraz z wynikającą z nich pracą trafia na jeden Rdzeń . To obciążenie jednego rdzenia wydłuża czas oczekiwania na usługi i zmniejsza efektywną przepustowość. Sprawdzam zatem, czy jest to zjawisko systematyczne, czy tylko Szczyty prowadzi.

Główne punkty pomiarowe: prawidłowe odczytywanie katalogu /proc i narzędzi

Zacznę od katalogu /proc/softirqs, ponieważ tam mogę sprawdzić, jak bardzo obciążony jest każdy procesor w zależności od typu, na przykład NET_RX, NET_TX, TIMER lub BLOCK. W katalogu /proc/net/softnet_stat sprawdzam wiersze, zwracając uwagę na pola sygnalizujące przekroczenie limitów lub utratę pakietów, co przy stałym wzroście wyraźnie wskazuje na zbyt krótkie Cykle odpytywania wskazuje. /proc/interrupts pokazuje następnie, czy przerwania sprzętowe rozkładają się nierównomiernie na procesory oraz które IRQ są najintensywniejsze. Narzędzia takie jak mpstat, top czy htop pomagają mi zidentyfikować ksoftirqd/cpuN oraz rozkład Czasy Softirq oceniać dla każdego jądra. W razie potrzeby perf wskazuje punkty newralgiczne w stosie, co pozwala mi zidentyfikować procedury obsługi i ścieżki sterowników, które pochłaniają najwięcej czasu. Poniższa tabela zawiera podsumowanie najważniejszych punktów pomiarowych, wskaźników i typowych Działania razem.

Punkt pomiarowy Najważniejsze obszary/wskaźniki Interpretacja Działanie
/proc/softirqs NET_RX, NET_TX, BLOCK po CPU Widać nierównomierny rozkład obciążenia Dostosuj przypisanie IRQ, włącz RSS
/proc/net/softnet_stat Licznik budżetu/licznik spadków, trzeci Kolumna Budżety są zbyt małe, paczki pozostają niedostarczone Zwiększyć wartość netdev_budget/usecs, sprawdzić RPS
/proc/interrupts Liczba linii IRQ na CPU, mapowanie kolejki Zbyt wiele sygnałów IRQ na niewielkiej liczbie rdzeni Sprawdź irqbalance, ustaw smp_affinity
mpstat / perf %soft, punkty dostępowe, Stosy Widoczne dominujące węzły i rdzenie Priorytetowe traktowanie optymalizacji sterowników i stosu

Przyczyny i schematy występowania dużego obciążenia

Zacięcia wynikają często z bardzo wysokiego Przepustowość, wiele połączeń równoległych lub impulsów UDP, które dominują w NET_RX. Czasami domyślne ustawienia sterowników przewidują małe partie danych, co powoduje zbyt dużą liczbę przerwań i przeciążenie ksoftirqd, podczas gdy GRO/LRO pozostają niewykorzystane pozostałości. Niekorzystne powiązania powodują skupienie obciążenia na procesorze CPU 0, mimo że dostępnych jest kilka kolejek, a RSS mogłoby ułatwić rozłożenie obciążenia. W maszynach wirtualnych karty vNIC obciążają jądro hosta, co wydłuża czasy SoftIRQ w hoście kosztem gości zwiększa. Nakładki kontenerowe dodają kolejne pakiety do stosu, przez co proste przepływy nagle stają się bardziej skomplikowanymi ścieżkami. Dopiero połączenie dystrybucji, budżetu i Dozowanie daje to spójny obraz.

Ukierunkowane monitorowanie: uwidocznienie SoftIRQ

Aby zapewnić skuteczny monitoring, regularnie czytam /proc-Wybieram interfejsy i łączę je z metrykami hosta, takimi jak obciążenie i opóźnienia planowania. Koreluję wzrosty NET_RX z licznikami utraconych pakietów, aby ustalić, czy wzrasta jedynie przepustowość, czy też pakiety giną po drodze pobyt. Polecenie `mpstat` podaje mi dla każdego procesora udziały czasu poświęcone na SoftIRQ, podczas gdy `top`/`htop` pokazują rzucające się w oczy wątki typu `ksoftirqd/cpuN`. Za pomocą poleceń `perf record`/`perf top` identyfikuję kosztowne ścieżki, na przykład odciążanie sum kontrolnych, konsolidację GRO lub qdisc-Praca. Ślady oparte na eBPF lub ftrace pokazują początek i koniec działania handlerów, co pozwala mi ocenić czas ich działania oraz wpływ harmonogramowania. W ten sposób na podstawie metryk, wykresów czasowych i Hotspoty.

Optymalizacja za pomocą netdev_budget i netdev_budget_usecs

Jeśli ścieżka NAPI jest za krótka, stopniowo ją wydłużam net.core.netdev_budget oraz net.core.netdev_budget_usecs, aby przetwarzać więcej pakietów w każdym cyklu odpytywania. Obserwuję przy tym trzecią kolumnę w /proc/net/softnet_stat; jeśli wzrost maleje, zmiany są skuteczne, a opóźnienia krótszy. Zwiększam te wartości umiarkowanie, na przykład z 300 do 600 pakietów i z 2000 do 4000 mikrosekund, i sprawdzam, czy inne zadania zachowują wystarczającą ilość czasu procesora. Zbyt duże obciążenie blokuje harmonogram, dlatego ściśle monitoruję szczyty obciążenia, zmiany kontekstu i długości kolejki zadań do wykonania towarzyszyć. Ponadto warto sprawdzić parametry RPS/RFS, GRO/LRO oraz MTU, aby efektywnie wykorzystać funkcję grupowania i rozmiary pakietów. Aby ograniczyć zalew przerwań, biorę pod uwagę Koalescencja przerwań i dostosuj te same ustawienia w sterownikach NIC, o ile ta opcja jest dostępna jest.

Optymalizacja przydziału przerwań i powinowactwa IRQ

Aby uniknąć wąskich gardeł związanych z jednym rdzeniem, rozdzielam sygnały IRQ na kilka Procesory, albo za pomocą irqbalance, albo przy użyciu ręcznych masek smp_affinity. Kieruję się przy tym istniejącymi kolejkami kart sieciowych i włączam RSS, aby sprzęt równomiernie rozdzielał przychodzące strumienie, a każde jądro miało ułatwioną pracę Partie . Staram się nie mieszać sygnałów sterujących IRQ z intensywnymi ścieżkami danych, aby zachować lokalność pamięci podręcznej i przewidywalność. Prawidłowo ustawione powinowactwa zmniejszają opóźnienia i ograniczają utratę danych, ponieważ przetwarzanie SoftIRQ nie utknęło już na jednym rdzeniu pozostałości. Sterowniki często pokazują przyporządkowania kolejek do procesorów w sysfs; tam sprawdzam, czy każda kolejka ma odpowiedni rdzeń i czy nie powstają żadne asymetrie. Aby uzyskać bardziej szczegółowe informacje, korzystam z przewodników takich jak Powinowactwo IRQ, aby uwzględnić również aspekty NUMA i wpływ pamięci podręcznej uwzględnić.

Przewodnik praktyczny: Od objawów do rozwiązania

Na początku sprawdzam objawy: ksoftirqd/cpuN w programie top, udziały SoftIRQ na jądro w mpstat oraz wyraźne skoki wartości NET_RX. Następnie zbieram twarde dane z /proc/softirqs, /proc/net/softnet_stat i /proc/interrupts, aby zidentyfikować dominujące ścieżki i nierównomierne rozkłady. Następnie wprowadzam niewielkie poprawki, najpierw w budżetach netdev, a potem w powinowactwie IRQ i RSS, za każdym razem z dokładną Kontrola. Jeśli nadal występują spadki wydajności, sprawdzam ustawienia sterowników, opcje koalescencji, operacje offload oraz zachowanie GRO/LRO. W przypadku hostów maszyn wirtualnych lub kontenerów dodatkowo oceniam, w jaki sposób karty vNIC współdziałają ze stosem fizycznego hosta oraz gdzie Hotspoty rzeczywiście tak jest. Każdą zmianę oceniam na podstawie szeregów czasowych, dopóki wskaźniki i opóźnienia nie ustabilizują się na dobrym poziomie ziemia.

Najlepsze praktyki w zakresie zrównoważonej wydajności

Wprowadzam regularne monitorowanie liczników SoftIRQ, ponieważ tylko stałe Przejrzystość zapobiega ponownemu wystąpieniu wąskich gardeł. Aktualne wersje jądra są opłacalne, ponieważ NAPI i stos są wewnętrznie udoskonalane, co zapewnia rezerwy na trudne Obciążenia stworzyć. Konieczne jest zachowanie zrównoważonego rozłożenia obciążenia na wiele rdzeni, podobnie jak rozsądne budżety, które pobierają wystarczającą liczbę pakietów, nie przeciążając przy tym harmonogramu. W przypadku profili hostingowych z dużym ruchem HTTPS i API warto zwrócić uwagę na SoftIRQ w hostingu, ponieważ właśnie tam widać, jak bardzo dobór kart sieciowych (NIC), kolejek i optymalizacja wpływają na poprawę jakości usług. Przy planowaniu wydajności biorę pod uwagę rdzenie procesora, funkcje kart sieciowych, pamięć oraz strefy NUMA, aby zapewnić odpowiednie rezerwy, zanim Wskazówki pojawiają się. Dzięki temu platforma zachowuje wydajność i płynnie reaguje na zmiany sezonowe lub związane z kampaniami godziny szczytu.

softnet_stat w szczegółach: co naprawdę oznaczają te liczby

Aby precyzyjnie dopracować swoje umiejętności, czytam /proc/net/softnet_stat w trakcie działania i należy zwrócić szczególną uwagę na pierwsze kolumny. Pola początkowe zawierają liczbę przetworzonych i odrzuconych pakietów na każdy procesor, które trzecia kolumna wskazuje na presję czasową (w skrócie: zbyt mały budżet/za mało czasu, NAPI musi przerwać działanie). Jeśli spadki lub presja czasowa rosną liniowo wraz z obciążeniem, pierwszymi narzędziami są budżety lub koalescencja. Jeśli natomiast obserwuję szczyty bez trwałego wzrostu, a impulsy jedynie krótkotrwale zagęszczają pracę – wówczas częściej pomaga przetwarzanie wsadowe (GRO) niż duże budżety. Nowsze jądra rozszerzają statystyki o pola dotyczące RPS/RFS i limitów przepływu; jeśli wartości te rosną, rozkładam obciążenie w sposób bardziej świadomy poprzez RPS lub zmniejszam RFS, gdy jego operacje wyszukiwania stają się bardziej kosztowne niż przynoszą korzyści. Zawsze koreluję liczniki z /proc/softirqs: Jeśli wartość NET_RX na poszczególnych rdzeniach wzrasta wraz ze wzrostem obciążenia czasowego w softnet_stat, w pierwszej kolejności skupiam się na rozkładzie (IRQ/RSS), a dopiero w drugim etapie na zwiększeniu limitów.

RPS/RFS i XPS: opanowanie sterowania oprogramowaniem i optymalizacji kolejek

Jeśli brakuje sprzętowego RSS lub jest on niewystarczający, ustawiam RPS (Receive Packet Steering) w celu rozłożenia obciążenia odbiorczego na kilka rdzeni. Za pomocą rps_cpus przypisuję kolejkom odbiorczym takie rdzenie, które odpowiadają aktywnym procesom roboczym i, w miarę możliwości, Blisko NUMA znajdują się. W wielu sekwencjach dodaję RFS (Receive Flow Steering), dzięki czemu przychodzące pakiety trafiają tam, gdzie przetwarzane są powiązane gniazda – sprzyja to lokalności pamięci podręcznej, o ile tabele przepływów nie stają się wąskim gardłem. Po stronie wysyłającej pomaga XPS (Transmit Packet Steering) – dostosowanie wyboru kolejki nadawczej (TX) do przypisania aplikacji do procesora. Celem jest zapewnienie, by dany strumień danych był konsekwentnie przetwarzany przez tę samą kolejkę odbiorczą/nadawczą (RX/TX) oraz ten sam rdzeń, co pozwala zmniejszyć opóźnienia i GRO-Partie stają się większe. Zawsze testuję rozkłady stopniowo: najpierw aktywuję RPS w kilku kolejkach, mierzę efekt (utraty, %soft, opóźnienia), a następnie dodaję RFS/XPS. Jeśli RPS powoduje przeciążenie rdzeni lub pogorszenie wskaźnika trafień L3, ponownie zmniejszam maski procesora lub ściślej przypisuję kolejki do rdzeni odpowiednich usług.

NUMA, izolacja procesorów i interakcje z harmonogramem

Nawet najlepsze plany budżetowe i alokacje niewiele pomogą, jeśli operacje dostępu do pamięci odbywają się przez długie ścieżki NUMA. Dbam o to, by przerwania karty sieciowej (NIC), operacje NAPI oraz procesy wysyłające żądania odbywały się w miarę możliwości w ramach tej samej Domena NUMA pozostają. W konfiguracjach z dedykowanymi rdzeniami działającymi w czasie rzeczywistym lub o niskim opóźnieniu izoluję je za pomocą zasad dotyczących procesora i grup Cgroup oraz celowo nie dopuszczam tam do działania SoftIRQ. ksoftirqd nie powinny trafiać do izolowanych jąder, w przeciwnym razie pakiety będą się gromadzić niezauważenie. Z drugiej strony izolowane jądra nie mogą pozostawać całkowicie pozbawione obsługi IRQ, jeśli kończą ścieżki danych – to jasna kwestia powinowactwa i Sprzątanie-Strategia jest niezbędna. W przypadku obciążeń o rygorystycznych SLO unikam zbyt agresywnych priorytetów SCHED_FIFO/RR, które mogłyby wyprzeć wykonanie NAPI. Monitoruję długości kolejek Runqueue, liczbę wybudzeń oraz wskaźniki preempcji: jeśli czasy SoftIRQ rosną wraz ze wzrostem interaktywności aplikacji, dostosowuję ziarnistość i powinowactwa zamiast ogólnie zwiększać budżety.

qdisc, offload i Busy-Poll: równoważenie opóźnień i przepustowości

Na ścieżce Egress każda qdisc-Czas operacyjny procesora. Wybieram metodę odpowiednią do profilu: fq_codel pomaga w przypadku „puffer bloat” i wygładza skoki obciążenia, podczas gdy mq-wersje kart sieciowych z obsługą wielu kolejek. W przypadku czystej przepustowości danych na stabilnych łączach lżejszy qdisc może zminimalizować skoki opóźnień. Na wejściu warto precyzyjnie dostroić GRO/TSO/GSO: Większe partie obniżają częstotliwość SoftIRQ, ale w skrajnych przypadkach wydłużają czas przebywania pakietów w stosie. Sprawdzam, czy interwały opróżniania GRO lub odciążanie sprzętowe prowadzą do powstania zbyt dużych agregatów, które mogą negatywnie wpływać na działanie aplikacji. W przypadku ścieżek, w których opóźnienia mają kluczowe znaczenie, ustawiam busy_poll oraz stosuję funkcję `busy_read` w sposób kontrolowany, aby aktywnie pobierać pakiety ze sterownika – jednak tylko pod ścisłą obserwacją, aby inne zadania nie zostały pozbawione zasobów. Podobnie zgadzam się, że Koalescencja przerwań w przypadku skoków obciążenia: nieco dłuższe mikrosekundy sprzyjają przepustowości, natomiast zbyt długie opóźniają potwierdzenia ACK i wydłużają procesy uzgadniania połączenia. Ważne jest, aby każdą zmianę oceniać osobno: symulowane skoki obciążenia, rzeczywiste szczyty produkcyjne i okresy bezczynności często charakteryzują się różnymi profilami opóźnień.

Lista kontrolna diagnostyczna i bezpieczne przywrócenie poprzedniego stanu

Zmiany wprowadzam konsekwentnie, korzystając z krótkiej listy kontrolnej: 1) Potwierdzam objawy (ksoftirqd, %soft, Drops). 2) Sprawdzam rozkład (/proc/interrupts, Queue->CPU, stan RSS/RPS). 3) Dostosowuję budżety, sprawdzam efekt w softnet_stat obserwować (zmniejsza się presja czasowa, liczba utrat danych ustabilizowała się). 4) Dokonać precyzyjnej regulacji offloadów/koalescencji, sprawdzić qdisc. 5) Ponownie sprawdzić powiązania NUMA/CPU oraz cgroups. Każdy krok kończy się wyraźną poprawą wskaźników lub Cofnięcie do ostatniego dobrego stanu. Dokumentuję wartości docelowe i rzeczywiste (opóźnienie P95/P99, %soft na rdzeń, wskaźniki utraty pakietów, zmiany kontekstu), aby kolejne iteracje nie odbywały się na ślepo. Jeśli kilka niewielkich usprawnień nie przynosi ulgi, przerywam i szukam przyczyn strukturalnych (wąskie gardła w kolejkach, bloki aplikacji, wpływ pamięci masowej). Taka dyscyplina zapobiega błędnym korelacjom i chroni przed spiralami optymalizacji, które wprawdzie zwiększają przepustowość, ale pogarszają interaktywność i stabilność.

Jasne rozróżnienie przypadków granicznych i profili obciążenia

Świadomie rozróżniam transfery masowe, interfejsy API wrażliwe na opóźnienia oraz przesyłanie z dużymi skokami UDP-Ruch. W przypadku danych masowych wolę wcześniej stosować przetwarzanie partiami i koalescencję, o ile nie dochodzi do utraty pakietów. W przypadku ruchu API priorytetem jest dla mnie równomierny rozkład, ograniczone partie i stabilne opóźnienia E2E, nawet jeśli nominalna maksymalna przepustowość nieco spadnie. Z impulsami UDP radzę sobie najlepiej poprzez rozszerzenie kolejki i stosowanie afinności – zbyt duże budżety powodują w przeciwnym razie jedynie nasilenie zjawiska blokowania na początku kolejki (Head-of-Line-Blocking). Jeśli środowisko wykorzystuje wiele kontenerów lub przeskoków w sieciach nakładkowych, planuję dodatkową pracę stosu i szerzej rozkładam obciążenie SoftIRQ. Oprócz tego osobno oceniam obciążenia związane z zaporą sieciową i Conntrack: gdy tabele osiągają swoje granice, obciążenie SoftIRQ nieuchronnie wzrasta, niezależnie od tego, jak dobry jest rozkład IRQ. Dopiero gdy ścieżki dla poszczególnych profili są konsekwentnie zoptymalizowane, warto zająć się precyzyjnym dostrojeniem ostatnich kilku procent.

SoftIRQ w środowiskach chmurowych i kontenerowych

W środowiskach wirtualnych obciążenie przemieszcza się przez vSwitche, sieci nakładkowe i stosy hostów, dlatego analizuję zarówno systemy gościnne, jak i hosty—Metryki przeanalizuj. Długie czasy SoftIRQ w hoście bezpośrednio spowalniają kontenery i maszyny wirtualne, nawet jeśli systemy-goście wydają się działać płynnie praca. Sprawdzam zatem funkcje offloadu i koalescencji na fizycznej karcie sieciowej, podczas gdy RPS/RFS w hoście zapewnia lepszą dystrybucję obciążenia w ścieżce programowej. W przypadku obciążeń kontenerowych sprawdzam, czy limity Cgroup dla procesora i przetwarzania IRQ są odpowiednio ustawione, aby ważne usługi nie znalazły się w Kolejki umrzeć z głodu. Karty vNIC obsługujące wiele kolejek (multi-queue) z funkcją RSS poprawiają równoległość, o ile odpowiednio skonfigurowano powiązania i mapowania kolejek. Dzięki takiemu podejściu utrzymuję ścieżki danych na krótkich odcinkach, stabilizując Opóźnienia oraz pewną i powtarzalną wydajność.

Podsumowanie: Jak z łatwością opanować analizę SoftIRQ

Kto dokładnie analizuje obciążenie SoftIRQ, korzysta z jasno określonych punktów pomiarowych, bierze pod uwagę rozkłady i stosuje stopniowane Kroki. Zaczynam od /proc/softirqs i softnet_stat, porównuję te dane z ksoftirqd i mpstat, a na tej podstawie ustalam kolejność moich Środki. Najpierw dostosowuję parametry netdev_budget i netdev_budget_usecs, a następnie optymalizuję przypisanie IRQ, RSS oraz opcje przetwarzania wsadowego, takie jak GRO i offload. Każda zmiana jest niewielka, poddawana pomiarom i kontynuowana tylko wtedy, gdy przynosi pozytywny efekt, aż znikną utraty pakietów i Opóźnienia spadają. Ta dyscyplina zapobiega efektom ubocznym, zapewnia interaktywność na poziomie procesora i utrzymuje działanie usług nawet w okresach szczytowego natężenia ruchu responsywny. Dzięki temu wydajność systemu Linux pozostaje przejrzysta, niezawodna i elastyczna, bez ukrytych punktów newralgicznych, które Stabilność zagrozić.

Artykuły bieżące

Serwer Linux z wizualizacją obciążenia SoftIRQ w nowoczesnym centrum danych
Serwery i maszyny wirtualne

Analiza i optymalizacja wykorzystania SoftIRQ w systemie Linux

Dowiedz się, jak systematycznie analizować i optymalizować wykorzystanie SoftIRQ w systemie Linux, aby zwiększyć wydajność serwerów dzięki ukierunkowanemu dostrajaniu modułów netdev oraz lepszemu rozkładowi przerwań.