...

Linux PSI per un'analisi e un monitoraggio precisi delle prestazioni

Linux PSI mi fornisce metriche che mostrano per quanto tempo le attività rimangono in attesa della CPU, della memoria o dell'I/O, mettendo così in evidenza i veri colli di bottiglia. In questo modo riesco a individuare con precisione quando i sistemi si bloccano, invece di limitarmi a misurare il carico di lavoro, e a ricavare dai valori di pressione misure dirette per l'analisi delle prestazioni e il monitoraggio.

Punti centrali

  • parziale/completo: Segnale di allarme precoce vs. blocco critico
  • CPU/memoria/I/O: Stampa chiaramente separata per ciascuna risorsa
  • avg10/60/300: Intervallo di tempo per la valutazione delle tendenze
  • Gruppi C: Identificare i responsabili e le persone coinvolte
  • Innesco: Reagire automaticamente in caso di superamento della soglia

Cosa misura Linux PSI e perché è importante

Leggo da Pressione-Le metriche indicano quanto tempo di lavoro effettivo viene perso a causa della mancanza di tempo CPU, RAM o I/O. I classici valori di utilizzo mostrano solo il grado di impiego delle risorse, mentre PSI rivela con quale frequenza il sistema sia effettivamente inattivo. È proprio questo che rende visibile la differenza tra una coda breve e un blocco totale. In configurazioni dinamiche con container e distribuzioni dense, riesco così a individuare prima i colli di bottiglia e ad attribuirli in modo univoco a una risorsa. In questo modo, stabilisco le priorità delle misure di ottimizzazione in modo mirato ed evito di fare ipotesi sull’effettiva Causa.

Attivare e verificare PSI su Linux

Per prima cosa verifico se PSI è attivo controllando i file presenti in /proc/pressure Se leggo e vedo che CPU, memoria e I/O forniscono valori in quella sezione, significa che è tutto pronto. Se mancano dei dati, attivo PSI con il parametro di avvio del kernel psi=1 oppure mi assicuro che nel kernel sia impostato CONFIG_PSI=y. Questa funzionalità è disponibile a partire dal kernel 4.20 ed è spesso già abilitata nelle distribuzioni attuali. Per controlli rapidi bastano semplici comandi come cat /proc/pressure/cpu, che mi forniscono i valori avg10, avg60, avg300 e total. In questo modo so in pochi secondi se il mio sistema fornisce dati significativi Metriche fornisce.

Comprendere i file presenti in /proc/pressure

In /proc/pressure sono presenti tre file per CPU, memory e io, che restituiscono ciascuno due tipi di output: some e full. some indica che almeno un’attività ha dovuto attendere, mentre full segnala che tutte le attività non inattive sono bloccate contemporaneamente. Inoltre, ottengo medie mobili su intervalli di 10, 60 e 300 secondi, oltre a un valore totale cumulativo. Sulla base di queste finestre temporali, distinguo i picchi di breve durata dai problemi persistenti. In questo modo valuto con obiettività se si verificano solo picchi isolati o se si tratta di un problema persistente Pressione è disponibile.

"some" e "full" nella pratica

Considero “some” un indicatore precoce e “full” un allarme grave, poiché “full” descrive fasi in cui il lavoro produttivo è di fatto bloccato. Se “some” aumenta nella CPU, controllo lo scheduling, i lock e la distribuzione del carico; in questi casi può essere utile ottimizzare i thread o misurare il Misurare la latenza dello scheduler. Valori elevati di memory-some indicano spesso recuperi di pagine, swapping o allocazioni onerose. Se io-some aumenta, controllo le code, le priorità e gli accessi concorrenti. Non prendo decisioni basandomi sull’istinto, ma su criteri chiari Segnali.

Analisi a livello di sistema vs. analisi basata su cgroup

Primo, prendo in esame a livello di sistema Valori, per avere una visione d’insieme, e poi passo ai Cgroups per identificare le fonti. Con cgroup v2 trovo file “pressure” specifici per ogni servizio o container, il che mi permette di associarli a pod, slice o unità. Questo approccio separa i sintomi dalle cause, invece di attribuire in modo indiscriminato tutti i carichi all’host. Successivamente, regolo in modo mirato le quote, le quote di CPU o i limiti di memoria. In questo modo aumento l’equità e riduco le interferenze reciproche Influenza.

PSI nel monitoraggio, nei dashboard e in Kubernetes

Raramente raccolgo i dati PSI manualmente, ma lascio che Exporter esporti i dati come serie temporali raccogliere i dati in modo che i dashboard mostrino tendenze e correlazioni. In Kubernetes leggo i PSI a livello di nodo, pod e container, il che consente una chiara separazione tra consumo e colli di bottiglia per ogni carico di lavoro. In questo modo riesco a capire se un singolo pod sta aumentando i tempi di attesa per gli altri o se il problema si verifica a livello di nodo. Impostiamo avvisi in caso di andamenti "full" e di valori "some" costantemente elevati. Ciò ci consente di reagire in modo proattivo, prima che gli utenti subiscano tempi di attesa sentire.

Scenari di utilizzo tipici e soglie appropriate

Utilizzo PSI nei test di carico per verificare se i tempi di risposta aumentano a causa di un sovraccarico della CPU, della memoria o dell’I/O e se tale aumento è di breve durata o permanente. Nella pianificazione della capacità, monitoro avg300 per individuare modelli ricorrenti e ampliare le risorse o spostare i carichi di lavoro in tempo utile. Per l’autoscaling utilizzo trigger vicini alla soglia in cui si verifica lo stato «full», in modo da poter reagire tempestivamente. In caso di progressivo peggioramento delle prestazioni, confronto le linee di base prima e dopo le release per rendere trasparenti gli effetti. In questo modo prendo decisioni basate sui fatti e investo dove c’è il maggior Effetto sorge.

Verifica rapida delle metriche PSI sotto forma di tabella

Quando analizzo i dati PSI, mi avvalgo di una semplice classificazione per arrivare più rapidamente all’ipotesi corretta. La tabella seguente sintetizza l’interpretazione dei valori “some” e “full” per ciascuna risorsa e fornisce alcune opzioni operative iniziali. Non sostituisce un’analisi più approfondita, ma mi fa risparmiare tempo prezioso durante il funzionamento. Resta fondamentale valutare i picchi di breve durata in modo diverso rispetto alle fasi più lunghe. Proprio a questo scopo utilizzo i valori medi mobili avg10, avg60 e avg300 come Contesto.

Risorse some-Signal segnale completo Cause più comuni Possibili misure
CPU Attese occasionali Tutte le attività sono bloccate Conflitti di scheduler, blocchi, numero eccessivo di thread Regolare i pool di thread, allentare i blocchi, adeguare le quote e le ripartizioni della CPU
Memoria Reclaim, errori di pagina, congestione delle allocazioni Forte pressione, lo swap domina Overcommit, heap di grandi dimensioni, pressione sulla cache Verificare i limiti, ottimizzare le allocazioni, ridurre lo swapping
I/O Code sempre più lunghe I/O è un termine generico Dischi/rete sovraccarichi, accessi concorrenti Priorità, raggruppamento, ottimizzazione delle code, volumi separati

Interpretare correttamente la pressione di accumulo

Valuto il valore di `memory.pressure` in combinazione con l’RSS, le percentuali di cache e l’utilizzo dello swap, poiché solo questa combinazione fornisce indicazioni attendibili. Spesso, un valore elevato di `some` è dovuto a una fase di liberazioni intensive o a un aumento dei page fault, che può essere attenuato con modelli di allocazione più efficaci. Se compare il valore «full», interrompo gli esperimenti e riduco innanzitutto la pressione impostando dei limiti o utilizzando cache meno aggressive. Un approfondimento sull’argomento mi viene fornito da Pressione di memoria con consigli pratici sull'ottimizzazione della RAM. In questo modo evito che lo swapping incontrollato allunga i tempi di risposta domina.

Individuare e risolvere i colli di bottiglia nell'I/O

Analizzo io.pressure insieme alle latenze, ai tassi di re-queue e alle profondità delle code, perché i valori di throughput da soli nascondono i colli di bottiglia. Un valore elevato di some a carico moderato mi indica spesso profili di accesso irregolari, che possono essere livellati tramite il batching o la prioritizzazione. In caso di ritardi sul primo byte e di aumento del valore «full», punto sul disaccoppiamento tramite I/O asincrono e volumi separati per gli hotpath. Per diagnosi dettagliate utilizzo serie di misurazioni e la guida collaudata nell’uso quotidiano su Analisi dell'attesa I/O. In questo modo prendo decisioni mirate invece di Ipotesi.

PSI vs. Load Average e metriche classiche

Metto volutamente il PSI a confronto con il Load Average, l’utilizzo della CPU, l’iowait e l’utilizzo della memoria, per colmare le lacune tra queste diverse prospettive. Un carico elevato con un valore basso di cpu.pressure spesso mi indica solo che molte attività possono eseguire calcoli attivamente, senza congestioni a livello di sistema. Al contrario, un aumento di cpu.pressure a fronte di un carico moderato è indice di conflitti di schedulazione o di contesa sui lock. Per quanto riguarda l’I/O, vale quanto segue: l’iowait da solo non mi dice quanto ne risenta l’intero sistema; l’io.pressure quantifica invece quanto tempo di lavoro viene perso in questo contesto. È proprio questa traduzione del concetto di “carico” in “tempo perso” a rendere le mie decisioni decisamente più affidabili.

Finestra AVG e lettura estremamente precisa

Considero i valori avg10/60/300 come percentuali del tempo in cui le attività sono state bloccate. Un valore avg10 pari a 2,50 significa che negli ultimi 10 secondi sono stati persi 2,51 TP3T di tempo di lavoro potenziale. Il valore «total» accumula il tempo di stallo dall’avvio del sistema (in unità di tempo ad alta risoluzione) e mi mostra quindi il Area sotto la curva. Per la pianificazione della capacità, osservo la pendenza dei profili giornalieri rispetto a quelli totali: se la linea diventa nettamente più ripida nelle fasi di picco, pianifico un alleggerimento del carico. Per i segnali operativi valuto gli andamenti: un breve picco in avg10 mi preoccupa meno di un aumento parallelo di avg60 e avg300, che indica una pressione strutturale.

Cgroups nella pratica: struttura, percorsi e permessi

Lavoro con cgroup v2 utilizzando i file “pressure” direttamente nelle rispettive directory di servizio, slice o pod. In questo modo riesco a capire, per ogni unità, pod o container, se la pressione viene generata localmente o se viene semplicemente trasferita. In questo modo è possibile distinguere chiaramente tra unità systemd, pod Kubernetes e gruppi definiti dall’utente. Una volta effettuata la classificazione, applico una limitazione mirata: quote CPU più restrittive, quote CPU più eque, limiti di memoria realistici. In pratica, mi assicuro di effettuare la misurazione proprio dove ha effetto, ovvero nel Cgroup che imposta i limiti. Questo mi impedisce di combattere i sintomi in un punto, mentre la vera fonte rimane intatta.

Strategie di allerta senza un'ondata di allarmi

Definisco gli allarmi in modo che tengano conto delle tendenze e della persistenza. Per il rilevamento precoce, imposto le soglie su “some”, le combino con finestre di osservazione e isteresi, e verifico se avg10 e avg60 rimane elevato. Per gli interventi urgenti, associo il valore “full” a finestre temporali brevi e reazioni automatiche (scalabilità, prioritizzazione, limitazione). Per evitare fluttuazioni, attivo l’intervento solo quando uno stato è stato confermato più volte e lo disattivo solo quando i valori scendono significativamente al di sotto della soglia di ritorno. Colleghiamo gli avvisi agli SLO dei servizi: se le latenze p95 aumentano e contemporaneamente cresce la pressione, il risultato è attendibile – il semplice carico di lavoro da solo non mi basta a questo scopo.

Esempi pratici: modelli che riconosco immediatamente

Mi piace raccogliere schemi ricorrenti perché accelerano il processo decisionale:

  • CPU: contesa per il blocco anziché “numero insufficiente di core” – Il valore di cpu.some aumenta, anche se il carico della CPU non è al limite. Sto analizzando gli hotlock, riducendo il thread splitting e livellando i picchi con la backpressure. Spesso questo porta a risultati migliori rispetto all’aggiunta di core aggiuntivi.
  • Memoria: Spirale di recupero – memory.some aumenta e oscilla a causa dei page fault, mentre viene attivato lo swap. Riduco l’aggressività della cache, riduco i picchi dell’heap (ad es. le dimensioni dei batch), adeguo i limiti e in questo modo impedisco che memory.full diventi visibile.
  • I/O: Accessi sbilanciati – io.some aumenta pur mantenendo invariata la larghezza di banda. Disaccoppio i percorsi di lettura/scrittura, raggruppo le operazioni I/O di piccole dimensioni in batch e distribuisco gli hotpath su volumi dedicati. In questo modo riduco i tempi di attesa senza necessariamente aumentare la larghezza di banda pura.

Limiti e ostacoli nell'interpretazione

Tengo presente che PSI misura il tempo di attesa, non il carico assoluto. Un processo batch CPU-bound può mostrare un carico elevato senza aumentare il cpu.pressure, purché siano disponibili abbastanza core. Al contrario, una bassa produttività con un io.pressure elevato può indicare un chiaro ingorgo. Negli ambienti virtualizzati verifico inoltre se i limiti o le affinità generano colli di bottiglia locali: un container fissato solo a pochi core può mostrare un cpu.pressure elevato, anche se l’host dispone di risorse libere. È importante anche confrontare la visione a livello di sistema con quella locale del cgroup: solo così posso capire se sto risolvendo il problema nel posto giusto.

Linee guida operative: campionamento, overhead e visualizzazione

Per quanto riguarda il campionamento, lo mantengo semplice: un intervallo di 1–5 secondi mi è sufficiente per le decisioni operative, poiché le finestre avg provvedono già a smussare i picchi. Considero trascurabile l’overhead di PSI, soprattutto perché mantengo la misurazione vicina al sistema e registro solo poche serie temporali ben posizionate. Per la visualizzazione, affianco i pannelli per ciascuna risorsa (some/full, avg10/60/300, total) e li metto in correlazione con la latenza e i tassi di errore. Nelle analisi post-mortem traccio l’andamento del valore «total» in funzione delle implementazioni, delle release o delle modifiche di configurazione: in questo modo diventa chiaro quali misure riducono effettivamente la pressione.

Misure mirate per ciascuna risorsa

Da questi modelli deduco delle misure concrete, senza ricorrere d'istinto all'aggiunta di hardware:

  • CPU: Limitare i pool di thread e i concurrency guard, mitigare gli hotlock (granularità/strategia di blocco), distribuire equamente il carico (quote/quote), tenere conto della topologia (NUMA, affinità). Solo quando l’alleggerimento locale non è sufficiente, procedo alla scalabilità orizzontale o verticale.
  • Memoria: Stabilizzare le allocazioni (batching, buffer), limitare l'uso delle cache, impostare limiti realistici, appiattire i picchi dell'heap, ridurre l'influenza dello swap. Effettuo misurazioni mirate prima e dopo le modifiche, poiché memory.some è sensibile ai modelli di allocazione.
  • I/O: Ottimizzare i profili di accesso (elaborazione in batch, I/O asincrono), disaccoppiare gli hotpath, impostare le priorità, scegliere profondità di coda adeguate e separare i carichi di lavoro concorrenti. Valuto i risultati in base alla diminuzione della pressione I/O e alla riduzione delle latenze P99.

PSI nella quotidianità del lavoro di squadra: comunicazione e senso di responsabilità

Utilizzo PSI anche come linguaggio comune tra i team della piattaforma e quelli di prodotto. Invece di parlare in modo astratto di “lentezza”, indico la risorsa e il modello: “io.some avg60 da 20 minuti oltre 4% nel servizio X” o “memory.full si attiva nel cgroup Y”. Questa precisione facilita la definizione delle priorità, perché è chiaro chi debba intervenire e quale budget (tempo, risorse) prometta i risultati migliori. Attraverso linee di riferimento definite, concordo obiettivi di qualità che siano sia tecnicamente validi sia comprensibili per gli stakeholder.

Trigger, linee di base e implementazione graduale

Utilizzo i trigger PSI con valori di soglia e finestre di monitoraggio, in modo che un demone reagisca automaticamente quando la pressione rimane elevata. Per ottenere risultati affidabili, prima di apportare modifiche creo una linea di riferimento basata sulle fasi di carico tipiche, che in seguito confronto con nuove serie di misurazioni. Definisco gli avvisi in modo prudente: un valore “some” costantemente elevato mi dà tempo, mentre “full” attiva le contromisure. Nelle grandi flotte implemento gli avvisi basati su PSI in più fasi, per evitare il “rumore” e regolare con precisione le tolleranze. In questo modo il mio monitoraggio rimane chiaro e affidabile, senza sovraccaricare i team con segnalazioni superflue.

Vantaggi per l'hosting, la virtualizzazione e l'architettura multi-tenant

Con PSI verifico se singoli carichi di lavoro ne rallentano altri, se le riserve hardware sono sufficienti e dove è necessario adeguare i limiti. Negli ambienti condivisi, individuo la pressione costante esercitata su CPU, memoria o I/O da singoli account e pianifico per tempo i trasferimenti. I valori basati sui cgroup mi indicano quali servizi sono interessati e dove posso limitare o assegnare priorità in modo mirato. In questo modo mantengo tempi di risposta affidabili e garantisco un utilizzo equo delle risorse anche sotto carico. Ciò riduce i costi, previene le escalation e aumenta la percettibile qualità.

Conclusione: dagli indicatori si prendono le decisioni

Utilizzo Linux PSI perché rende misurabili i tempi di attesa, colmando così il divario tra carico di lavoro ed esperienza utente. Con "some" riconosco i primi segnali, con "full" reagisco ai veri blocchi e con i Cgroups individuo le cause precise. Dashboard, trigger e baseline trasformano questa visione in azioni concrete: limiti ottimizzati, migliore distribuzione del carico, percorsi I/O puliti. Chi utilizza attivamente PSI riduce il tempo necessario per individuare la causa ed evita numerosi cicli di ottimizzazione alla cieca. In questo modo, i dati di monitoraggio diventano chiari Decisioni, che rendono i sistemi notevolmente più veloci.

Articoli attuali