Guide

Load average alto: capire chi consuma la CPU prima di cambiare server

Guida pratica per leggere il load average, distinguere CPU piena da attesa disco e capire quando serve davvero più potenza.

Redazione UptimeMag · 13 ottobre 2026 · 7 minuti di lettura

Real Estate

La verifica più rapida

Prima cosa, prima di leggere oltre: apri una shell e lancia

uptime

L'output finisce con tre numeri, tipo load average: 1.98, 2.15, 2.21. Sono la media dei processi in esecuzione o in attesa (CPU o disco) negli ultimi 1, 5 e 15 minuti. Poi conta i core:

grep processor /proc/cpuinfo | wc -l

Dividi il primo numero del load average per il numero di core. Se il risultato è sotto 1, il server non è sovraccarico, qualunque sia il numero assoluto. Un load average di 4 su un server a 8 core significa che quel carico riflette un workload che usa circa metà della potenza di elaborazione disponibile. Lo stesso 4 su un server a un solo core core è tutta un'altra storia: su un sistema a singola CPU un carico di 1.0 significa che la CPU è completamente utilizzata, su un sistema a 4 CPU un carico di 4.0 indica piena utilizzazione.

Questo vale su qualunque distribuzione Linux, cPanel o Plesk compresi: il comando uptime è identico, cambia solo dove poi vai a cercare la causa.

Cosa misura davvero il load average

Secondo la pagina di manuale di uptime(1), il load average è il numero medio di processi che sono in stato eseguibile o non interrompibile: un processo in stato eseguibile sta usando la CPU o aspettando di usarla, un processo in stato non interrompibile sta aspettando un accesso di I/O, ad esempio il disco. Quindi il numero da solo non dice se il collo di bottiglia è la CPU o il disco: lo dice la scomposizione che vedi con top o htop.

Una soglia pratica, non ufficiale ma ragionevole per iniziare a preoccuparsi: in condizioni normali si vuole che il load average resti al 70% o meno del totale della CPU usata; se il load average è più alto del numero di CPU disponibili, il sistema sta accodando richieste alla CPU, il che riduce le prestazioni.

I tre casi che si confondono

Lancia top (presente ovunque) o htop se installato. La riga che conta, sotto l'intestazione, è quella con le percentuali %Cpu(s): us (user), sy (system), wa (iowait), id (idle).

Caso Cosa vedi in top/htop Cosa significa
CPU davvero occupata us e sy alti, wa basso codice che gira, va ottimizzato o serve più CPU
Attesa del disco wa alto, us/sy bassi il processo aspetta I/O, non calcola nulla
Troppe richieste insieme molti processi in stato R nella colonna S, pochi singolarmente pesanti è un problema di concorrenza, non di potenza bruta

La distinzione fra i primi due casi è descritta anche nella documentazione del kernel: %sys è il tempo speso eseguendo codice del kernel, %wait è il tempo speso aspettando I/O; %iowait non è un'indicazione della quantità di I/O in corso, ma solo un'indicazione del tempo extra che il sistema mostrerebbe se i trasferimenti I/O non ritardassero l'esecuzione del codice. In pratica: iowait alto con CPU libera non si risolve comprando più core, si risolve capendo cosa aspetta il disco (database lento, snapshot in corso, swap).

Per isolare il terzo caso, un load average alto con CPU quasi tutta idle e wa basso, quasi sempre con molti processi D o R ma ciascuno leggero, è tipico di troppi worker PHP-FPM o troppe connessioni Nginx in coda insieme, più che di uno script che fa calcoli pesanti.

Collegare il carico al sito che lo genera (Ubuntu 24.04 con Nginx e PHP-FPM)

Qui serve passare da "il server è lento" a "questo sito, questa richiesta". Il pool PHP-FPM ha uno slow log che scrive lo stack trace delle richieste più lente di una soglia. Si abilita nel file di pool, ad esempio /etc/php/8.3/fpm/pool.d/www.conf:

slowlog = /var/log/php8.3-fpm-slow.log
request_slowlog_timeout = 5s

Con questa configurazione la slow log registra uno stack trace per le richieste che impiegano troppo tempo, e qualunque richiesta che supera i 5 secondi di request_slowlog_timeout ha il suo stack trace PHP scritto nella slow log, che mostra esattamente in quale funzione era bloccata. Dopo una modifica al file di pool serve ricaricare il servizio:

sudo systemctl reload php8.3-fpm

Poi si guarda lo slow log per vedere quale script e quale funzione stavano bloccando il worker:

tail -40 /var/log/php8.3-fpm-slow.log

La direttiva e il suo default sono documentati nel manuale ufficiale di PHP: request_slowlog_timeout è il timeout per servire una singola richiesta dopo il quale viene scritto un backtrace PHP nel file slowlog; il valore 0 significa disattivato, e slowlog è il file di log per le richieste lente, con valore di default #INSTALL_PREFIX#/log/php-fpm.log.slow, cioè nessun percorso fisso finché non lo imposti tu nel pool.

Per avere anche una vista d'insieme sul pool, oltre allo slow log si abilita la status page:

pm.status_path = /fpm-status

e la si interroga con una richiesta locale (va esposta solo da 127.0.0.1, non da internet) per vedere quanti worker sono occupati e se il pool ha raggiunto pm.max_children.

Su cPanel l'equivalente è l'interfaccia MultiPHP INI Editor più i log del PHP-FPM del dominio, che cPanel gestisce in automatico sotto /var/log/php-fpm/; su Plesk lo slow log si attiva dal pannello in "PHP Settings" per dominio, con il file scritto sotto la cartella di log del dominio. In entrambi i casi il principio è lo stesso del pool manuale: si alza una soglia bassa, si aspetta che il problema si ripresenti, si legge lo stack trace.

Per Nginx, se il sospetto è che il carico arrivi da troppe richieste in coda più che da PHP, la direttiva di log è documentata nella pagina ufficiale: Default: error_log logs/error.log error; (il percorso reale su Ubuntu è in genere /var/log/nginx/error.log, verificabile con grep error_log /etc/nginx/nginx.conf). Lì si vedono i timeout verso PHP-FPM (upstream timed out), che confermano se il collo di bottiglia è a monte del web server.

Come si risolve, caso per caso

CPU davvero occupata (us/sy alti). Non è un problema di configurazione del web server: è uno script, una query, un cron che consuma CPU. Si identifica il processo con top ordinato per CPU (tasto P in top/htop) e si risale al PID, poi al proprietario (sito o utente) con:

ps -o user,cmd -p PID

Se è legittimo e ricorrente, la risposta è ottimizzare il codice o la query, non necessariamente comprare più core. Se è uno script fuori controllo (loop, import bloccato), si uccide e si corregge.

Attesa del disco (wa alto). Si verifica con:

iostat -x 1 5

(pacchetto sysstat, da installare con sudo apt install sysstat su Ubuntu se manca). Se la colonna %util del disco è vicina a 100 mentre la CPU è libera, il disco è il collo di bottiglia: database senza indici, troppi I/O concorrenti, oppure — su una VPS — storage condiviso del fornitore sotto pressione. In quest'ultimo caso il problema può non dipendere da te.

Troppe richieste insieme. Si guarda la status page di PHP-FPM: se active processes è sempre vicino a pm.max_children, il pool è sottodimensionato per il traffico reale. Si alza pm.max_children solo se c'è margine di RAM libera; altrimenti si riduce la memoria per singolo worker o si mette una cache davanti (pagina statica, reverse proxy) per non far arrivare ogni richiesta a PHP.

Quando il problema può essere del fornitore

Su una VPS il load average che sale senza una causa visibile nei tuoi processi può dipendere dal nodo fisico condiviso (CPU steal time, storage in contesa con altri clienti). Si verifica lo steal time con top: nella riga %Cpu(s) c'è anche una colonna st. Se st è sistematicamente sopra qualche punto percentuale durante il picco di carico, è CPU che il tuo processo non ha mai avuto perché il fisico la stava dando ad altri. In quel caso si apre un ticket al provider allegando: orario preciso (con timezone) dell'evento, output di uptime nel momento del picco, output di top con la riga %Cpu(s) visibile, e se possibile iostat -x dello stesso intervallo. Senza questi dati l'assistenza non può distinguere un problema lato host da uno lato cliente.

Come si verifica che è risolto

Dopo l'intervento (ottimizzazione query, aumento worker, cache, o cambio piano) si rifà la stessa misura di partenza per lo stesso intervallo di traffico: uptime diviso numero di core sotto 1, wa tornato vicino a zero se era quello il problema, slow log di PHP-FPM che non si riempie più durante le ore di punta. Non basta un singolo controllo a freddo: va rifatto durante l'orario in cui il problema si manifestava, altrimenti si verifica solo che il server è tranquillo quando non c'è nessuno sopra.

Quando serve davvero più potenza

Più core o più CPU ha senso solo se il load average normalizzato resta sopra 1 durante il traffico ordinario, con CPU effettivamente piena (us+sy alti) e dopo aver già escluso query lente, cache mancante e pool PHP-FPM sottodimensionato. Se il problema è iowait, aggiungere CPU non cambia nulla: serve storage più veloce o meno I/O. Se il problema è un singolo picco isolato (un backup, un import), non serve cambiare piano: serve spostare quell'operazione fuori dall'orario di traffico.

Testo redatto con il supporto dell'intelligenza artificiale e verificato dalla redazione (AI Act, art. 50).