Tutti gli articoli
Performance10 min di letturaTeam WPsec.it

WordPress lento: come capire in 10 minuti se il collo di bottiglia è il server

Tre livelli, sei test con curl, Query Monitor, slow log e PHP-FPM, e una tabella che dice dove sta il collo di bottiglia. Poi chi lo risolve: il sito o il server.

Condividi
WordPress lento: come capire in 10 minuti se il collo di bottiglia è il server

"Il sito è lento" è la frase con cui iniziano metà dei ticket, e finiscono con due risposte che non aiutano: "il server è operativo" dal provider, "è l'hosting" dallo sviluppatore. Nessuno dei due ha misurato. Questa guida chiude la discussione in dieci minuti con numeri, e manda il problema al mestiere giusto: chi gestisce il sito o chi gestisce il server.

Quali sono i tre livelli in cui WordPress perde tempo?

  1. Rete e TTFB: DNS, connessione, TLS e il tempo che il server impiega a iniziare la risposta. Si misura da fuori, con curl.
  2. Server: PHP-FPM e database: worker PHP disponibili, OPcache, memoria e disco, MySQL con il suo buffer pool. Si misura da dentro, con accesso alla macchina o al pannello.
  3. Tema e plugin: il codice che gira a ogni richiesta, le query che genera, le chiamate HTTP che fa. Si misura con Query Monitor.

La regola: si parte dal livello 1 e si scende solo se i numeri lo dicono. La sequenza completa di priorità è nella guida sull'ordine giusto della diagnosi; qui interessa una domanda sola: sito o server.

Come si misura il TTFB in modo che dica qualcosa?

Un TTFB da solo non distingue niente. Scomposto sì:

curl -s -o /dev/null -w "dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} totale=%{time_total}\n" https://iltuosito.it/

Lettura:

  • tcp e tls alti (oltre 200-300 ms dall'Italia verso un server europeo): rete, DNS o un server che fatica ad accettare connessioni. Livello 1.
  • ttfb meno tls alto: il tempo lo passa il server a costruire la pagina. Da qui in poi si decide tra livello 2 e 3.

Ripeti tre volte e in due momenti della giornata: un valore che oscilla molto tra una misura e l'altra indica contesa di risorse (livello 2), un valore stabile e alto indica codice (livello 3). La lettura estesa del dato è nella diagnosi TTFB.

Qual è il test che separa il sito dal server?

Pagina statica contro pagina PHP. Misura un file che non passa da PHP, poi una pagina che ci passa per forza, poi la stessa pagina servita dalla cache:

# file statico servito dal web server, niente PHP
curl -s -o /dev/null -w "statico ttfb=%{time_starttransfer}\n" https://iltuosito.it/wp-includes/js/jquery/jquery.min.js

# pagina PHP forzando il miss di cache
curl -s -o /dev/null -w "php ttfb=%{time_starttransfer}\n" "https://iltuosito.it/?nocache=$(date +%s)"

# la stessa pagina dalla cache: guarda l'header di hit
curl -sI https://iltuosito.it/ | grep -iE "x-cache|cf-cache-status|x-litespeed-cache|^age:"
  • Statico lento (sopra 200-300 ms): il server o la rete sono lenti prima ancora di WordPress. Disco, web server saturo, macchina condivisa sovraffollata. Livello 1 o 2, in ogni caso non il tema.
  • Statico veloce, cache HIT lenta: il server fa fatica a servire perfino una risposta pronta. Livello 2.
  • Statico veloce, HIT veloce, MISS lento: il costo è nella generazione della pagina. Può essere PHP-FPM saturo (livello 2) o codice pesante (livello 3): lo decidono i prossimi due test.

Cosa guardare in Query Monitor per capire se è il codice?

Query Monitor è gratuito e va attivato sul sito, meglio su staging o in orario di basso traffico. Nella barra in alto trovi tempo totale, tempo PHP, tempo database e numero di query. La lettura:

  • Tempo DB alto con poche query lente dello stesso chiamante: un plugin o il tema fanno query pesanti. Livello 3, sito.
  • Tempo DB alto con tutte le query lente, anche quelle banali: MySQL è affamato di memoria o di disco. Livello 2, server.
  • Tempo PHP alto con tempo DB basso: codice che macina, oppure OPcache che non trattiene i file. Guarda la scheda delle chiamate HTTP API: una chiamata esterna sincrona (verifica licenze, feed, font) da due secondi è un classico del livello 3.
  • Centinaia di query per pagina: sito, quasi sempre un plugin di related posts, un widget social o un builder che carica tutto.

Quali numeri del server chiudono la diagnosi?

Servono accesso SSH o un pannello che li esponga. Quattro comandi, un minuto ciascuno (i percorsi dei log cambiano con la distribuzione):

# 1. load rispetto ai core
uptime; nproc

# 2. worker PHP attivi e volte in cui il limite è stato raggiunto
ps -eo comm | grep -c php-fpm
grep -c "max_children" /var/log/php*fpm*.log

# 3. memoria, swap, CPU rubata e iowait
free -m; vmstat 1 5

# 4. MySQL: buffer pool e slow log
mysql -e "SHOW GLOBAL VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%'; SHOW GLOBAL VARIABLES LIKE 'slow_query_log%';"

Come leggerli:

  • load stabilmente sopra il numero di core e vmstat con la colonna r piena: CPU contesa. Su hosting condiviso guarda anche st (steal): se supera il 5-10 percento, la macchina fisica è sovraffollata e nessun tuning del sito lo risolve.
  • "server reached pm.max_children setting" nel log di PHP-FPM: i worker sono finiti e le richieste si mettono in coda. È il caso più frequente di "lento a scatti" e non ha niente a che fare con il tema.
  • swap in uso o wa (iowait) alto: memoria insufficiente o disco lento, spesso i due insieme.
  • Innodb_buffer_pool_reads che cresce rispetto a Innodb_buffer_pool_read_requests: MySQL legge da disco perché il buffer pool è più piccolo dei dati. Con un buffer pool sotto il gigabyte su un WooCommerce medio è quasi certo.
  • slow log spento: nessuno ha mai guardato le query. Attivalo con long_query_time=1 per un'ora e leggi il risultato con mysqldumpslow -s t.
  • OPcache: va letta dal processo PHP-FPM, non dalla CLI, che ha una cache separata (con cachetool opcache:status o una pagina temporanea che stampa opcache_get_status()). num_cached_keys vicino a max_cached_keys o oom_restarts sopra zero significa che i file PHP vengono ricompilati di continuo: un sito con molti plugin ha decine di migliaia di file, il default opcache.max_accelerated_files è pensato per quattromila.
  • wp-cron a ogni visita: grep -c wp-cron.php access.log nelle ultime ore. Se compare a ogni richiesta e ci sono decine di eventi in coda, ogni utente paga il lavoro di sfondo. Si sposta su cron di sistema con DISABLE_WP_CRON.

Se vedi X, il collo è Y

Se vediIl collo èLivelloChi interviene
tcp o tls sopra 300 msRete, DNS o server che non accetta connessioni1Server
File statico lentoDisco, web server, macchina condivisa satura1-2Server
Cache HIT lentaServer in sofferenza anche a costo zero2Server
"max_children" nel log PHP-FPMWorker PHP esauriti2Server
Load sopra i core, st altoCPU contesa, hosting sovraffollato2Server (o cambio piano)
Innodb_buffer_pool_reads in crescitaBuffer pool sottodimensionato2Server
OPcache piena o con restartOPcache sottodimensionata2Server
Tutte le query lente, anche banaliMySQL affamato di risorse2Server
Poche query lente, stesso chiamantePlugin o tema con query pesanti, indici mancanti3Sito
Chiamata HTTP esterna nel tempo PHPPlugin con verifica remota sincrona3Sito
Centinaia di query per paginaPlugin o builder3Sito
wp-cron a ogni richiestaCron di WordPress non disaccoppiato2-3Sito + server
TTFB ok, LCP altoImmagini, script, font: non è il server3Sito

L'ultima riga merita una nota: immagini non ottimizzate e JavaScript del tema non toccano il TTFB. Se il tuo problema è il rendering, il server non c'entra e il percorso è quello dei Core Web Vitals.

Cosa chiedere al provider, e cosa vuol dire "il server è operativo"?

"Il server è operativo" vuol dire che la macchina risponde al ping, i servizi girano e non ci sono guasti hardware. Non dice nulla sui worker PHP del tuo account, sulla dimensione del buffer pool, sul disco condiviso con altri cento siti. È una frase vera e inutile.

Chiedi numeri, non aggettivi:

  1. quanti worker PHP ha il mio account (o il mio pool) e quante volte nelle ultime 24 ore è stato raggiunto il limite;
  2. il load medio della macchina e il numero di core;
  3. se il mio account ha toccato i limiti di CPU, memoria, I/O o processi (su CloudLinux si vede in "Utilizzo risorse");
  4. la dimensione di innodb_buffer_pool_size e se lo slow log è attivo;
  5. il tipo di disco e la percentuale di utilizzo.

Se la risposta è "tutto regolare" senza un numero, hai già la risposta: quel livello non lo gestisce nessuno.

Se è il server, chi lo mette a posto?

Il perimetro conta più dello strumento. Del sito si occupa WPsec.it: query di plugin e tema, cache, autoload di wp_options, chiamate esterne, cron di WordPress, immagini e rendering. Il servizio corrispondente è velocizzare WordPress, con la scheda tecnica in ottimizzazione performance: misura prima e dopo, verifica di integrità inclusa, perché un sito lento perché infetto non si ottimizza, si bonifica. I costi sono nella pagina prezzi.

Del server si occupa managedvps.it, il servizio della stessa squadra tecnica dedicato alla macchina Linux: PHP-FPM, OPcache, MySQL, disco, memoria, web server. Se i test ti hanno portato al livello 2 e non hai un sistemista, la diagnosi e ottimizzazione lato server è l'intervento una tantum; la gestione del server è il caso in cui vuoi che quei numeri li guardi qualcuno anche il mese prossimo.

Se sei su hosting condiviso il livello 2 non è tuo: puoi solo chiedere i numeri al provider e, se non arrivano, cambiare piano. Con i test qui sopra almeno lo fai sapendo cosa stai comprando.

Come faccio a capire se WordPress è lento per colpa del server o del sito?

Misura un file statico e una pagina PHP con curl. Se anche il file statico è lento, è il server o la rete. Se il file vola e la pagina PHP è lenta, apri Query Monitor: query pesanti di un solo plugin o chiamate esterne indicano il sito; tutte le query lente, worker PHP esauriti o load sopra i core indicano il server.

Quanto deve essere il TTFB di un sito WordPress?

Sotto 200 ms per una pagina servita dalla cache, entro 500-600 ms per una pagina dinamica su un server sano. Oltre 800 ms c'è un problema strutturale: cache assente, worker PHP saturi, database sottodimensionato o un plugin pesante. Il valore da solo non basta: va scomposto in connessione, TLS e tempo di generazione.

Cambiare hosting risolve un WordPress lento?

Solo se il collo è al livello 2 e il nuovo piano ha davvero più worker PHP, più memoria per MySQL e un disco migliore. Un plugin che fa 400 query per pagina resta lento anche sul server più costoso. Misura prima con i test di questa guida: se il problema è il codice, il cambio hosting è una spesa senza effetto.

Cosa vuol dire quando il provider risponde che il server è operativo?

Che la macchina risponde e i servizi sono attivi. Non dice nulla sui limiti del tuo account, sui worker PHP, sul buffer pool di MySQL o sul disco condiviso. Chiedi numeri precisi: worker e volte in cui il limite è stato raggiunto, load e core, limiti toccati, dimensione del buffer pool, tipo di disco.

Pubblicato il

Condividi

Scritto dal team WPsec.it

Team WPsec.it

Bonifica malware, hardening, performance e manutenzione WordPress.

Prevenzione e gestione

Dopo l'emergenza, o per non arrivarci: le guide sulla gestione.

Sicurezza, velocità e manutenzione di WordPress sono lo stesso lavoro visto da tre lati. Queste pagine spiegano cosa controllare, con quale priorità e quanto costa farlo fare.

Continua a leggere

Articoli correlati.