...

Gestione degli interrupt sui server: come gli interrupt della CPU influenzano le prestazioni

Gli interrupt della CPU controllano la velocità con cui il server risponde ai pacchetti di rete, agli eventi di storage e ai timer: interruzioni distribuite in modo errato o troppo frequenti rallentano le applicazioni in modo misurabile. Un server con una gestione pulita degli interrupt riduce gli switch di contesto, abbassa le latenze e stabilizza i tempi di risposta durante i picchi di carico.

Punti centrali

Prima di entrare nel dettaglio, riassumerò i seguenti aspetti chiave:

  • Carico di interruzione capire: Quando i valori percentuali diventano critici
  • Parallelismo gestire: interrupt simultanei e latenze del caso peggiore
  • MSI-X utilizzo: Più notizie, migliore distribuzione
  • RSS Affinità: collocare gli interrupt della NIC sui core
  • Monitoraggio stabilire: Leggere i numeri, agire in modo mirato

Cosa fa scattare gli interrupt della CPU sui server

Un'interruzione è un Segnale, che interrompe immediatamente l'attività corrente della CPU e avvia un gestore. Le schede di rete segnalano nuovi pacchetti, i controller di archiviazione segnalano l'I/O completato, i timer attivano gli orologi: ognuno di questi interrupt costa denaro. tempo di CPU. Con un'attività elevata, questi eventi si sommano a molti context switch e cache miss. Per questo motivo, monitoro la frequenza e il tempo che la CPU del kernel dedica alle ISR e ai DPC. Se si comprendono queste dinamiche, è possibile controllare i tempi di risposta in modo affidabile e far funzionare le applicazioni in modo sensibilmente più fluido.

Perché i tempi di interruzione elevati costano le prestazioni

In ambienti sani, le interruzioni del sistema sono di solito comprese tra 0,1-2% CPU, 3-7% sono possibili a breve termine. Se il tempo di interruzione rimane regolarmente al di sopra di 5-10%, spesso si tratta di un problema di driver, di hardware difettoso o di tuning errato. A partire da 30% la situazione si fa seria, oltre 50% c'è la minaccia di Colli di bottiglia e tempi di risposta lenti. Le applicazioni perdono throughput, le latenze saltano e la prevedibilità ne risente. Per prima cosa controllo le versioni dei driver, il firmware, le affinità e la moderazione degli interrupt sulle NIC.

Interruzioni simultanee: capire le latenze

Un singolo interrupt raramente rimane un Problema; Diventa difficile quando diversi eventi si scontrano. Se un interrupt ad alta priorità si verifica durante un interrupt a bassa priorità, la sua elaborazione viene prolungata da ulteriori interruzioni. Un esempio: se il percorso ad alta priorità richiede 75 cicli e quello a bassa priorità 50, la latenza del percorso a bassa priorità sale facilmente a 125 cicli - ulteriori sovrapposizioni aumentano la latenza. Il caso peggiore-La latenza aumenta rapidamente. Questo comportamento rende i sistemi imprevedibili. Pertanto, pianifico le affinità e le priorità del nucleo in modo tale che i percorsi caldi non si blocchino a vicenda.

MSI e MSI-X nell'uso quotidiano

Gli host moderni utilizzano MSI o MSI-X, invece di inviare i classici segnali di linea (linee IRQ). MSI trasmette il messaggio come scrittura in memoria, riducendo così la latenza e la suscettibilità alle interferenze. MSI-X estende il concetto: più messaggi, code separate, distribuzione più precisa ai core. In questo modo si riducono le collisioni di interrupt e si migliora il Scala con un throughput elevato. Attivo MSI-X per le schede NIC e i controller NVMe, purché i driver e il firmware lo supportino in modo stabile.

meccanismo Max. Messaggi Indirizzamento Distribuzione ai core Effetto tipico
IRQ legacy 1 per dispositivo/linea Segnale di linea Limitato Più alto Latenza, più collisioni
MSI Fino a ~32 Scrittura di memoria (16 bit) Buono Meno spese generali, percorsi più stabili
MSI-X Fino al 2048 Scrittura di memoria (32 bit) Molto buono Più fine Distribuzione, parallelismo superiore

DMA, DPC e il giusto percorso dei dati

Con il DMA, i dispositivi possono memorizzare i dati direttamente nella memoria di Memoria La CPU attiva solo le routine di elaborazione. In questo modo si risparmiano gli interrupt, perché devono essere segnalati meno stati intermedi. Mi assicuro che i DPC raggruppino il lavoro effettivo invece di fare troppo nell'ISR. In questo modo, il tempo nella sezione critica è breve e il tempo di elaborazione è ridotto. Latenza più prevedibile. Nel complesso, la CPU guadagna più tempo per la logica applicativa.

Configurare in modo specifico l'affinità RSS e CPU

Il Receive Side Scaling distribuisce le code di rete e i relativi interrupt su più nuclei. Lego ogni coda, compresi interrupt, DPC e thread utente, allo stesso core o cluster di core per evitare scosse incrociate tra core. Se in un flusso sono coinvolti diversi core, aumentano le perdite di cache e i context switch. Un piano di affinità strutturato evita notevolmente queste perdite per attrito. Se si desidera approfondire, è possibile trovare una guida compatta Affinità della CPU-Panoramica delle configurazioni di hosting.

Disinnescare gli interrupt di archiviazione e i percorsi di I/O

Lo stoccaggio genera anche molti Interruzioni, soprattutto con molti piccoli IOPS. Uso MSI-X sui controller NVMe e assegno le code a core fissi in modo che l'input e l'output rimangano locali. Inoltre, un'adeguata Schedulatore I/O, per attenuare il carico per coda. Le varianti Deadline, BFQ o MQ reagiscono in modo molto diverso a seconda del carico di lavoro. Se si esegue il test in modo corretto, si riduce il jitter e si aumenta la Produttività.

Tempeste di rete, SYN flood e moderazione delle interruzioni

Improvvise inondazioni di pacchi spingono la PVR-e togliere il fiato alla CPU. Attivo la moderazione degli interrupt sulla NIC, in modo che i pacchetti arrivino in raffiche ragionevoli senza generare picchi di latenza. Per gli scenari DoS, un sistema resiliente di Difesa dalle inondazioni SYN la tabella delle connessioni in una fase iniziale. Allo stesso tempo, misuro se la moderazione stessa reagisce troppo lentamente, quindi regolo i valori. L'obiettivo è ottenere un flusso di pacchetti omogeneo che distribuisca uniformemente i DPC. alimentazioni.

Monitoraggio: leggere e agire sui dati

Inizio con pochi, chiari MetricheUtilizzo totale della CPU, tempo di interruzione, tempo DPC, cambio di contesto e coda del processore. Se la CPU rimane generalmente al di sotto di 50%, reagisco con calma; a 50-80% osservo i picchi e gli hotspot; al di sopra di 80% pianifico il ridimensionamento o la messa a punto. Se il tempo di interruzione supera i 30%, controllo il driver, il firmware e le affinità. Un controllo della latenza per l'audio/video mostra indirettamente la determinatezza della reazione del kernel. Importante: modifico solo un Variabile per ogni prova e poi misurare di nuovo.

Topologia NUMA e localizzazione PCIe

Sugli host multi-socket, decido sempre le affinità di interruzione nel contesto dell'ambiente di lavoro di NUMA-topologia. Un NIC o un controller NVMe è fisicamente collegato a un complesso root PCIe e quindi a un nodo NUMA. Se imposto le code e i loro interrupt su distante i dati viaggiano attraverso i collegamenti UPI/QPI: le latenze aumentano, la larghezza di banda diminuisce. Pertanto, controllo a quale nodo NUMA è assegnato un dispositivo, lego le sue code ai core locali e mi assicuro che i thread utente associati utilizzino lo stesso nodo. Su Windows, faccio attenzione ai gruppi di processori e all'impostazione del dispositivo per il nodo NUMA preferito; su Linux, collego costantemente IRQ, softirq e thread applicativi al nodo locale. Il risultato: meno traffico tra i nodi, maggiore stabilità. Jitter-e latenze calcolabili nel caso peggiore.

Utilizzo corretto di offload, NAPI e coalescenza

Gli offload sono potenti leve contro l'interrupt flood, ma devono essere usati per Carico di lavoro in forma. Riassumendo: TSO/GSO spostano la segmentazione sulla NIC, LRO/GRO riassumono i segmenti in arrivo, RSC sull'host ha un effetto simile a LRO. Per i trasferimenti di massa (backup, replica), queste caratteristiche aumentano il throughput e riducono significativamente il tasso di ISR. Tuttavia, per i flussi critici in termini di latenza (RPC, trading, VoIP), le grandi aggregazioni possono avere un impatto negativo sul tasso di PVR. Tempi di risposta estendere. Pertanto, scelgo impostazioni moderate: GRO sì, ma senza esagerare; LRO solo se nessun dispositivo o firewall di medio percorso crea problemi; lasciare TSO/GSO attivo come regola.

NAPI su Linux passa dalla modalità di interrupt puro alla modalità di polling a partire dal carico. In questo modo si attenuano i picchi e si tiene occupata la CPU nel percorso DPC, invece di innescare migliaia di brevi ISR. Insieme a Interruzione della moderazione (coalescenza), viene creato un piano: timer brevi per i profili interattivi, timer più lunghi per quelli di massa. Testiamo gli intervalli con incrementi di microsecondi, osserviamo le cadute, i livelli di riempimento degli anelli e le latenze per trovare il punto giusto. Nello stack di archiviazione, le viti di regolazione analogiche (profondità della coda, NCQ, ottimizzazioni blk-mq) producono lo stesso effetto: meno staccato, più Efficienza.

Bilanciamento IRQ vs. pinning statico

Il bilanciamento automatico degli IRQ distribuisce il carico in modo accettabile, ma non perfetto. In ambienti web omogenei, spesso lo lascio in funzione e controllo solo gli hotspot. Nelle configurazioni critiche per la latenza o asimmetriche Pinzatura statica superiore: Definisco set di CPU fissi per ogni coda e dispositivo, li mantengo coerenti attraverso i riavvii e riduco al minimo la migrazione delle softirq. Inoltre, riservo i core „di mantenimento“ per il lavoro in background (timer, Kthread) in modo che i core per le prestazioni rimangano liberi. Su Windows, utilizzo specificamente il pilotaggio degli interrupt e le maschere di affinità per ogni coda; su Linux, lavoro con l'affinità per-IRQ e il controllo delle Softirq. Il motto: tutta l'automazione necessaria, tutta l'automazione necessaria. Determinismo il più possibile.

Virtualizzazione e SR-IOV/virgolette

Nelle macchine virtuali sorgono costi aggiuntivi: gli interrupt virtuali significano Uscita della macchina virtuale, ritardi di schedulazione e code condivise. Collego le vCPU ad alta intensità di I/O a pCPU adeguate, evito l'overcommit sugli host di I/O e separo i thread del dataplane dal carico di gestione. Dove possibile, utilizzo SR-IOVLe funzioni virtuali portano MSI-X alla VM guest e riducono il carico sul percorso dell'hypervisor. Per i carichi di lavoro generici, virtio con l'accelerazione vhost offre risultati solidi; negli scenari ad alto rendimento, mappo le code 1:1 alle vCPU e mantengo le affinità coerenti da guest a host. Importante: le stesse regole per RSS, coalescenza e NUMA sono valide anche per le macchine virtuali, solo che il Trasparenza è più basso, quindi misuro più attentamente.

Gestione dell'alimentazione e latenze deterministiche

Le funzioni di risparmio energetico sono buone per il bilancio, ma cattive per il lavoro. Budget di latenza. Gli stati C profondi allungano il tempo di risveglio e le variazioni di frequenza aggressive causano jitter. Sugli host con SLO rigorosi, imposto profili di prestazioni, limito gli stati C profondi del pacchetto e permetto il turbo solo quando la riserva termica è sufficientemente ampia. Anche le decisioni relative ai timer (timer ad alta risoluzione o frequenza di interrupt inferiore) influenzano la quantità e la velocità di lavoro del kernel. Nelle configurazioni quasi in tempo reale, le modalità tickless e i core isolati sono d'aiuto: i thread delle applicazioni sui core isolati, il lavoro di sistema sui core „di mantenimento“ dedicati - in modo che i core critici Percorso caldo libero da incendi interferenti.

Strumenti e metodologia di misurazione per OS

Tengo il mio Catena diagnostica snello e riproducibile. Su Linux inizio con /proc/interrupts e /proc/softirqs, controllo i contatori per-queue tramite ethtool ed esamino le impostazioni di coalescenza e offload. mpstat, vmstat e sar mostrano le tendenze macro; perf scopre i punti caldi nelle ISR/DPC. Metto in relazione i contatori dei pacchetti e dei drop con i tempi del kernel e le metriche di flusso. Su Windows, gli indicatori di prestazione sul tempo di interrupt/DPC, interrupt/sec e DPC/sec forniscono un quadro chiaro; le tracce mostrano quali driver stanno regolando il tempo. Importante è il comune Scala temporaleRegistro tutto in modo sincronizzato in modo che i picchi, le cadute e i salti di latenza corrispondano.

Playbook e anti-pattern per la risoluzione dei problemi

La mia procedura è coerente: prima Osservare, poi un'ipotesi, quindi una modifica. Le cause tipiche sono: una coda o un dispositivo con un tasso crescente di PVR, un firmware difettoso, valori di coalescenza troppo alti (sistema duro) o troppo bassi (tempesta di PVR), offload troppo grandi o thread che tirano le code attraverso i nodi NUMA. Isolo il dispositivo interessato, verifico le impostazioni predefinite, modifico i driver/BIOS e distribuisco il carico in modo pulito. Antipattern: spostare tutto allo stesso tempo, rollback disordinati, nessuna linea di base o letture senza contesto. Se si utilizza costantemente un dispositivo Variabile dopo l'altro, si arriverà rapidamente a una configurazione stabile.

Progetti per host 10/25/100G e NVMe

Per le NIC 10G, calcolo 4-8 code RSS, a seconda della generazione di CPU e del profilo dei pacchetti. Inizio la coalescenza con moderazione (ad esempio, microsecondi a due cifre), GRO on, LRO con attenzione. A 25G passo a 8-16 code e mantengo l'affinità strettamente NUMA-local. A partire da 40/100G, l'architettura delle code diventa il Compito principaleMolte code, allocazione pulita per core, offload attivo, il NAPI entra in funzione sotto carico. Per lo storage NVMe, mappo almeno una coda per core e mantengo la profondità della coda adatta al carico di lavoro: i piccoli I/O beneficiano di un maggiore parallelismo, i trasferimenti sequenziali di grandi dimensioni di una politica di coalescenza stabile e di uno scheduler che attenua i burst. L'obiettivo rimane lo stesso: latenze costanti, nessun core caldo, nessun anello traboccante.

Lista di controllo pratica per un rapido successo

Io aggiorno per primo Autisti e BIOS/firmware, perché gli stati difettosi spesso aumentano il carico di interrupt. Poi, se possibile, passo a MSI-X e distribuisco le code in modo pulito ai core. Configuro l'RSS in modo che le affinità di flusso siano corrette e gli hotpath siano coerenti. Sul NIC, adatto la moderazione al profilo di traffico e osservo l'effetto sulle latenze. Se continuo a trovare valori anomali, cerco hardware difettoso, opzioni non corrette o dispositivi problematici utilizzando la procedura di esclusione e una procedura separata. Profilazione.

Valutare realisticamente costi e benefici

Non tutti i sistemi hanno bisogno del massimo Sintonizzazione fine. Do la priorità agli host con un carico di pacchetti elevato, molti IOPS ridotti o specifiche di latenza ristrette. Alcune ore di messa a punto sono molto utili in questo caso, perché la riduzione dell'overhead degli interrupt libera immediatamente la CPU per l'applicazione. Sui server non critici, è sufficiente una solida configurazione di base con i driver più recenti e MSI-X. Sono i valori misurati a guidarmi, non le sensazioni di pancia o le Ipotesi.

Sommario: Cosa metto in valigia per la manutenzione quotidiana

Osservo costantemente Interruzione- e DPC, mantengo aggiornati i driver e il firmware e utilizzo MSI-X ove possibile. Pianifico RSS e affinità per carico di lavoro in modo che flussi, DPC e thread rimangano locali. Adeguo la moderazione NIC agli schemi del traffico, distribuisco le code di archiviazione in modo pulito e utilizzo percorsi di I/O adeguati. Se il monitoraggio mostra dei valori anomali, mi occupo direttamente dei driver, dell'hardware e della configurazione. In questo modo, il server di gestione degli interrupt rimane prevedibile e i miei carichi di lavoro vengono eseguiti con stabilità. Prestazioni.

Articoli attuali