...

Analysera och optimera SoftIRQ-belastningen i Linux

Jag visar steg för steg hur jag Linux SoftIRQ-mätar belastningen, synliggör flaskhalsar och återfår kontrollen med några få justeringar i kärnan. Därvid prioriterar jag mätbara effekter: kortare Fördröjningar, balanserade CPU-kärnor och stabil paketbehandling vid hög nätverksbelastning.

Centrala punkter

  • Mätpunkter förstå: /proc/softirqs, softnet_stat, interrupts
  • Symptom identifiera: belastning på ksoftirqd, paketförluster, latensspikar
  • Tuning styr: netdev_budget och netdev_budget_usecs
  • Distribution spara: IRQ-affinitet, RSS, kö-mappning
  • Övervakning genomföra: mpstat, perf, spårning

Översikt över SoftIRQ: Hur kärnan fungerar

Efter ett hårdvaruavbrott flyttar kärnan delar av arbetet till så kallade SoftIRQs, så att kritiska vägar snabbt frigörs och bearbetningen förblir planerbar. Särskilt i nätverksvägen samlar NAPI-hanterare in paket från NIC-ringarna, initierar protokollbearbetning och överlämnar data till Nätverksstack. Om antalet händelser ökar träder trådar per CPU, såsom ksoftirqd/cpuN, in och tar över avfrågningen samt efterbearbetningen. Denna avkoppling förbättrar den totala genomströmningskapaciteten, men kan vid överbelastning leda till långa SoftIRQ-körtider på enskilda Kärnor leder till. Jag håller därför ett öga på om NET_RX- och NET_TX-vägarna dominerar och om ksoftirqd synligt slukar CPU-tid. På så sätt kan jag upptäcka när SoftIRQ:er blir en flaskhals och ytterligare Optimeringar är nödvändiga.

Identifiera typiska symptom på hög SoftIRQ-belastning

En betydande SoftIRQ-belastning märker jag först genom en konstant hög Kärn-CPU och ksoftirqd-processer som håller toppvärden under flera sekunder. Samtidigt ökar latensen för nätverks- och block-I/O, vilket märks i tröga TLS-handskakningar eller sega API:er uttrycks. Ofta uppstår paketförluster samtidigt som nätverkskortets ringar överbelastas och eftersläpningarna växer. Om avbrott fördelas dåligt drabbas ofta CPU 0 hårt, eftersom många IRQ-linjer tillsammans med efterföljande bearbetning hamnar på en Kärnan . Denna bindning till en enda kärna ökar väntetiderna för tjänsterna och minskar den effektiva genomströmningen. Jag undersöker därför om detta mönster är systematiskt eller om det bara beror på Toppar leder till.

Viktiga mätpunkter: Att tolka /proc och verktygen på rätt sätt

Jag börjar med /proc/softirqs, eftersom jag där kan se, per CPU och typ, hur mycket ungefär NET_RX, NET_TX, TIMER eller BLOCK ökar. I /proc/net/softnet_stat granskar jag raderna med fokus på fält som indikerar överskridna budgetar eller bortkastade paket, vilket vid en stadig ökning tydligt tyder på att Avstämningscykler tyder på. /proc/interrupts visar sedan om hårdvaruavbrott fördelas ojämnt mellan processorerna och vilka IRQ:er som är mest aktiva. Verktyg som mpstat, top eller htop hjälper mig att identifiera ksoftirqd/cpuN och fördelningen av Softirq-tider bedömas per kärna. Vid behov visar perf var det finns flaskhalsar i stacken, så att jag kan hitta hanterare och drivrutinsvägar som tar mycket tid. Tabellen nedan sammanfattar de viktigaste mätpunkterna, indikatorerna och typiska Åtgärder tillsammans.

Mätpunkt Viktigaste områden/indikatorer tolkning Åtgärd
/proc/softirqs NET_RX, NET_TX, BLOCK vardera CPU Ojämn lastfördelning kan konstateras Justera IRQ-affinitet, aktivera RSS
/proc/net/softnet_stat Budget-/drop-räknare, tredje Kolumn Budgeten är för liten, paketen blir liggande Öka netdev_budget/usecs, kontrollera RPS
/proc/avbrott IRQ-Lines pro CPU, kömappning För många IRQ:er på för få kärnor Kontrollera irqbalance, ställa in smp_affinity
mpstat / perf %soft, Hotspots, Staplar Dominerande handtag och kärnor synliga Prioritera optimering av drivrutiner och stackar

Orsaker och mönster bakom hög belastning

Spetsar uppstår ofta på grund av mycket hög Genomströmning, många parallella anslutningar eller UDP-bursts som dominerar NET_RX. Ibland är standardinställningarna i drivrutinerna inställda på små batcher, vilket leder till för många avbrott och överbelastar ksoftirqd, medan GRO/LRO förblir outnyttjade kvarlevor. Ogynnsamma affiniteter koncentrerar belastningen till CPU 0, trots att flera köer skulle vara tillgängliga och RSS skulle kunna underlätta fördelningen. I virtuella maskiner belastar vNIC:er värdkärnan, vilket ökar SoftIRQ-tiderna i värden på bekostnad av gästerna ökar. Container-overlays lägger till ytterligare paket i stacken, vilket gör att enkla flöden plötsligt blir mer krävande vägar. Det är först kombinationen av fördelning, budget och Batchning ger en helhetsbild.

Målmedveten övervakning: synliggöra SoftIRQ:er

För att kunna bedriva en hållbar övervakning läser jag regelbundet /proc-gränssnitt och kopplar dem till värdmetriker som belastning och schemaläggningsfördröjningar. Jag korrelerar ökningar i NET_RX med antalet tappade paket för att avgöra om det bara är genomströmningen som ökar eller om paket går förlorade längs vägen stanna. mpstat visar tidsfördelningen för SoftIRQ:er per CPU, medan top/htop visar de iögonfallande ksoftirqd/cpuN-trådarna. Med perf record/perf top identifierar jag resurskrävande processer, till exempel avlastning av kontrollsummor, GRO-sammanslagning eller qdisc-Arbete. eBPF- eller ftrace-baserade spårningar visar när hanterarna startar och avslutas, vilket gör att jag kan utvärdera hanterarnas körtider och schemaläggningseffekter. På så sätt får jag en tydlig överblick utifrån mätvärden, tidsförlopp och Hotspots.

Justering med netdev_budget och netdev_budget_usecs

Om NAPI-vägen inte räcker till ökar jag stegvis net.core.netdev_budget och net.core.netdev_budget_usecs, för att kunna bearbeta fler paket per avfrågningscykel. Jag håller då koll på den tredje kolumnen i /proc/net/softnet_stat; om ökningen avtar innebär det att ändringarna har gett önskad effekt och att latenserna blir kortare. Jag höjer värdena måttligt, till exempel från 300 till 600 paket och från 2000 till 4000 mikrosekunder, och kontrollerar om andra uppgifter fortfarande får tillräckligt med CPU-tid. För mycket blockerar schemaläggaren, varför jag noggrant övervakar belastningstoppar, kontextbyten och längden på körkön följ med. Dessutom är det värt att kontrollera RPS/RFS, GRO/LRO och MTU för att kunna utnyttja batchning och paketstorlekar på ett effektivt sätt. För att minska antalet avbrott tar jag hänsyn till Sammanslagning av avbrott och justera motsvarande inställningar med NIC-drivrutinerna, om den här reglaget är tillgängligt är.

Optimera fördelningen av avbrott och IRQ-affinitet

För att undvika flaskhalsar i en enda kärna fördelar jag IRQ:er på flera Processorer, antingen via irqbalance eller med manuella smp_affinity-masker. Då utgår jag från de befintliga NIC-köerna och aktiverar RSS, så att hårdvaran fördelar inkommande flöden jämnt och varje kärna får arbetsunderlättande Batcher får. Jag ser till att inte blanda ihop styr-IRQ:er med kritiska datavägar för att upprätthålla cache-lokalitet och planerbarhet. Korrekt inställda affiniteter minskar latenser och minskar bortfall, eftersom efterbearbetningen av SoftIRQ inte längre fastnar på en kärna kvarlevor. Drivrutinerna visar ofta kopplingarna mellan köer och CPU:er i sysfs; där kontrollerar jag om varje kö har en passande kärna och att inga asymmetrier uppstår. För en mer ingående analys utgår jag från riktlinjer som IRQ-affinitet, för att även beakta NUMA-aspekter och cache-effekter beakta.

Praktisk handbok: Från symptom till lösning

Till att börja med kontrollerar jag symptomen: ksoftirqd/cpuN i top, andelen SoftIRQ per kärna i mpstat och påfallande NET_RX-toppar. Därefter samlar jag in konkreta fakta från /proc/softirqs, /proc/net/softnet_stat och /proc/interrupts för att kartlägga dominerande vägar och skeva fördelningar. Därefter genomför jag små finjusteringar, först av netdev-budgetarna, följt av IRQ-affinitet och RSS, i båda fallen med noggrann Kontroll. Om förluster fortfarande syns kontrollerar jag drivrutinsinställningar, coalescing-alternativ, avlastningar och GRO/LRO-beteende. I VM- eller container-värdar utvärderar jag dessutom hur vNIC:erna interagerar med den fysiska värdstacken och var Hotspots verkligen ligger. Jag utvärderar varje förändring utifrån tidsserier tills nyckeltalen och latenserna har stabiliserats på en bra nivå land.

Bästa praxis för hållbar prestanda

Jag inför regelbunden övervakning av SoftIRQ-räknarna, eftersom endast konstanta Öppenhet förhindrar att flaskhalsar återkommer. Aktuella kärnversioner lönar sig eftersom NAPI och stacken förbättras internt, vilket skapar reserver för tunga Belastningar skapa. En balanserad fördelning över flera kärnor är fortfarande ett måste, liksom väl avvägda budgetar som hämtar tillräckligt många paket utan att överbelasta schemaläggaren. För hostingprofiler med mycket HTTPS- och API-trafik lönar det sig att ta en titt på SoftIRQ vid webbhotell, eftersom det där framgår hur mycket valet av nätverkskort, köer och finjustering förbättrar tjänstekvaliteten. Vid kapacitetsplaneringen tar jag hänsyn till CPU-kärnor, nätverkskortens funktioner, minne och NUMA-zoner, så att det finns reserver innan Tips inträffa. På så sätt förblir plattformen stabil och reagerar smidigt på säsongs- eller kampanjrelaterade Trafiktoppar.

softnet_stat i detalj: Vad siffrorna egentligen betyder

För att förfina mina kunskaper läser jag /proc/net/softnet_stat under processens gång och tolka särskilt de första kolumnerna. De första fälten visar antalet bearbetade och avvisade paket per CPU, vilka tredje kolumnen pekar på tidspress (kort sagt: för liten budget/för kort tidsram, NAPI måste avbryta). Om avbrotten eller tidspressen ökar linjärt med belastningen är budgetar eller coalescing de första åtgärderna. Om jag däremot ser toppar utan varaktig ökning, så komprimerar bursts bara arbetet på kort sikt – då hjälper batching (GRO) oftare än stora budgetar. Nyare kärnor utökar statistiken med fält för RPS/RFS och flödesgränser; om dessa ökar fördelar jag arbetet mer medvetet över RPS eller minskar RFS när dess uppslag blir dyrare än nyttan. Jag korrelerar alltid räknarna med /proc/softirqs: Om NET_RX ökar på enskilda kärnor samtidigt som tidspressen i softnet_stat ökar, fokuserar jag först på fördelningen (IRQ/RSS) och först i ett andra steg på större budgetar.

RPS/RFS och XPS: Full kontroll över programvarustyrning och köoptimering

Om det saknas hårdvarubaserad RSS eller om den inte räcker till, använder jag RPS (Receive Packet Steering) för att fördela mottagningsbelastningen på flera kärnor. Via rps_cpus tilldelar jag mottagningsköerna sådana kärnor som passar de aktiva arbetarna och, om möjligt, Nära till NUMA ligger. I många flöden lägger jag till RFS (Receive Flow Steering), så att inkommande paket hamnar där de tillhörande socklarna bearbetas – bra för cache-lokaliteten, så länge flödestabellerna inte blir en flaskhals. På sändarsidan hjälper XPS (Transmit Packet Steering), att anpassa valet av TX-kö till applikationens CPU-bindning. Målet är att ett flöde konsekvent ska gå via samma RX/TX-kö och samma kärna, vilket minskar latensen och GRO-Batcharna blir större. Jag testar alltid fördelningar stegvis: först aktiverar jag RPS på ett fåtal köer, mäter effekten (bortfall, %soft, latenser) och lägger sedan till RFS/XPS. Om kärnorna blir överbelastade av RPS eller om L3-träfffrekvensen försämras, minskar jag CPU-maskerna igen eller kopplar köerna närmare kärnorna för de berörda tjänsterna.

NUMA, CPU-isolering och interaktioner mellan schemaläggare

Även de bästa budgeterna och fördelningarna hjälper föga om minnesåtkomsterna tar långa NUMA-vägar. Jag ser till att NIC-avbrott, NAPI-efterbearbetning och de processer som gör förfrågningarna i möjligaste mån sker inom samma NUMA-domän förblir. I konfigurationer med dedikerade realtids- eller latenskärnor isolerar jag dessa med hjälp av CPU- och Cgroup-policyer och undviker medvetet att låta SoftIRQ-processer köras där. ksoftirqd bör inte hamna på isolerade kärnor, annars hopar sig paket utan att man märker det. Omvänt får isolerade kärnor inte lämnas helt utan IRQ-hantering när de avslutar datavägar – en tydlig affinitet och Städning-En strategi är ett måste. För arbetsbelastningar med strikta SLO:er undviker jag alltför aggressiva SCHED_FIFO/RR-prioriteringar som skulle kunna tränga undan NAPI-körningen. Jag övervakar längden på körköerna, uppvaknanden och preemptionsfrekvensen: Om SoftIRQ-tiderna ökar i takt med att appens interaktivitet växer justerar jag granulariteten och affiniteterna istället för att generellt höja budgetarna.

qdisc, avlastningar och Busy-Poll: Balansera latens och genomströmning

På utgångsvägen kostar varje qdisc-CPU-tid. Jag väljer den metod som passar profilen: fq_codel motverkar bufferbloat och jämnar ut dataströmmar, medan mq-varianter av Multi-Queue-NIC:er. Vid ren datagenomströmning på stabila länkar kan en lättare qdisc minimera latensspikar. På ingressen lönar det sig att finjustera GRO/TSO/GSO: Större batcher sänker SoftIRQ-frekvensen, men ökar i gränsfall paketets kvarhållningstid i stacken. Jag mäter om GRO-flush-intervall eller hårdvaruavlastningar leder till för stora aggregat som skadar applikationen. För vägar där latensen är mycket kritisk ställer jag in busy_poll och använder busy_read i lagom mängd för att aktivt hämta paket från drivrutinen – men endast under noggrann övervakning, så att andra uppgifter inte svälter ut. På samma sätt ställer jag in Sammanslagning av avbrott När det gäller plötsliga trafikökningar: att öka mikrosekunderna något förbättrar genomströmningen, men för mycket fördröjer ACK-svar och förlänger handskakningarna. Det är viktigt att utvärdera varje förändring separat: simulerade trafikökningar, verkliga produktionstoppar och perioder med låg belastning uppvisar ofta olika latensprofiler.

Diagnoslista och säker återställning

Jag går konsekvent igenom ändringar med hjälp av en kort checklista: 1) Dokumentera symptomen (ksoftirqd, %soft, Drops). 2) Kontrollera fördelningen (/proc/interrupts, Queue->CPU, RSS/RPS-status). 3) Justera budgetarna, effekten i softnet_stat övervaka (tidspressen minskar, antalet avbrott stagnerar). 4) Finjustera offloads/coalescing, granska qdisc. 5) Dubbelkolla NUMA/CPU-bindningar och cgroups. Varje steg avslutas med en tydlig förbättring av mätvärdena eller med Rollback till det senaste godkända läget. Jag dokumenterar mål- och faktiska värden (latens P95/P99, %soft per kärna, avbrottsfrekvens, kontextbyten) så att senare iterationer inte sker i blindo. Om flera små förbättringar inte leder till någon avlastning avbryter jag och letar efter strukturella orsaker (köflaskhalsar, appblockeringar, lagringspåverkan). Denna disciplin förhindrar felaktiga korrelationer och skyddar mot optimeringsspiraler som visserligen ökar genomströmningen men försämrar interaktiviteten och stabiliteten.

Att tydligt skilja mellan gränsfall och arbetsbelastningsprofiler

Jag gör medvetet skillnad mellan bulköverföring, latenskritiska API:er och burstig UDP-Trafik. För stora datamängder använder jag batchning och sammanslagning tidigare, så länge det inte förekommer paketförluster. Vid API-trafik prioriterar jag jämn fördelning, begränsade batcher och stabila E2E-fördröjningar, även om den nominella maximala genomströmningen minskar något. UDP-bursts hanterar jag helst genom köutvidgning och affiniteter – för stora budgetar ökar annars bara head-of-line-blockering. Om en miljö använder många container- eller overlay-hopp planerar jag in extra stackarbete och sprider SoftIRQ-belastningen bättre. Jag utvärderar dessutom överhead för brandväggar och conntrack separat: När tabellerna når sina gränser ökar SoftIRQ-belastningen oundvikligen, oavsett hur bra IRQ-fördelningen är. Först när vägarna per profil är konsekvent smala lönar det sig att finjustera de sista procenten.

SoftIRQ:er i moln- och containermiljöer

I virtualiserade miljöer flyttas belastningen via vSwitches, överlagringsnätverk och värdstackar, vilket är anledningen till att jag både gäst- och värd-Mätetal analysera. Långa SoftIRQ-tider i värdsystemet bromsar omedelbart ner containrar och virtuella maskiner, även om gästsystemen till synes fungerar utan problem arbete. Jag kontrollerar därför avlastning och sammanslagning på det fysiska nätverkskortet, medan RPS/RFS i värddatorn fördelar mjukvarubanan bättre. För containerbaserade arbetsbelastningar kontrollerar jag om Cgroup-gränserna för CPU och IRQ-efterbearbetning är rimligt inställda, så att viktiga tjänster inte hamnar i Köer svälta ihjäl. vNIC:er med stöd för flera köer och RSS förbättrar parallelliteten, förutsatt att affiniteterna och kömappningarna stämmer. Med detta perspektiv håller jag datavägarna korta och stabiliserar Fördröjningar och säker, reproducerbar prestanda.

Sammanfattning: Att behärska SoftIRQ-analys med säker hand

Den som analyserar SoftIRQ-belastningen på ett korrekt sätt använder tydliga mätpunkter, granskar fördelningar och tillämpar differentierade Steg. Jag börjar med /proc/softirqs och softnet_stat, jämför med ksoftirqd och mpstat och fastställer utifrån detta ordningen på mina Åtgärder. Först justerar jag netdev_budget och netdev_budget_usecs, därefter optimerar jag IRQ-affinitet, RSS samt batchningsalternativ som GRO och offloads. Varje justering är liten, mäts och fortsätter endast om den ger en positiv effekt, tills förlusterna försvinner och Fördröjningar minskar. Denna disciplin förhindrar biverkningar, upprätthåller interaktiviteten på CPU:n och säkerställer att tjänsterna fungerar även under trafiktoppar lyhörd. På så sätt förblir Linux-prestandan transparent, robust och anpassningsbar, utan att dolda flaskhalsar påverkar Stabilitet äventyra.

Aktuella artiklar