Early Access Provare la demo dal vivoDemo , si apre in una nuova scheda
Tecnologia

WordPress, servito senza PHP

Ogni visita a una pagina WordPress avvia un worker PHP. Il worker carica il core di WordPress, il tema e tutti i plugin attivi, apre una connessione a un server MySQL, esegue il loop e poi smonta quasi tutto. Lo rifà a ogni richiesta.

Il suo sito è fatto di tre cose: i contenuti, il tema che li mostra e il wp-admin con cui li modifica. BookPress tiene queste tre cose e cambia tutto quello che sta sotto.

Il percorso di servizio è una riscrittura da zero in C++. Router, renderer dei temi a blocchi, livello delle query e wp-admin sono codice nativo, non PHP. PHP gira soltanto per i suoi temi e plugin, sul motore PHP di BookPress. Un sito senza plugin fa tutto il lavoro senza eseguire PHP.

Può provarne uno. La demo dal vivo è il tema Kadence con WooCommerce, Elementor, Yoast SEO, Contact Form 7, Yoast Duplicate Post e Hello Dolly tutti attivi, servito da questo motore su una e2-micro di Google Cloud senza cache delle pagine davanti. Le credenziali compaiono quando avvia la sandbox. Scriva un articolo. La sandbox sparisce 15 minuti dopo l'avvio, quindi non ci metta nulla di personale.

Il motore

I temi, renderizzati davvero

BookPress renderizza i temi a blocchi di WordPress in modo nativo. Legge gli stessi file template, lo stesso markup dei blocchi e lo stesso theme.json, e produce l'HTML e il CSS che produrrebbe WordPress: stili globali, classi di layout, preset dei font, tipografia fluida. Twenty Twenty-Five, il tema predefinito di WordPress, oggi viene reso quasi al pixel dai suoi file originali, web font inclusi.

Il wp-admin segue la stessa strada. /wp-login.php verifica gli hash delle password WordPress che ha già. /wp-admin le dà bacheca, elenchi degli articoli ed editor, serviti dallo stesso motore alla stessa velocità.

Il confronto: una prova in salita per BookPress

Prendiamo un sito vero: tema Kadence con WooCommerce, una vetrina costruita con Elementor, Yoast SEO e Contact Form 7. Migriamo gli stessi contenuti nei due motori, con lo stesso numero di righe nei due database. Prima di misurare mettiamo a punto il lato WordPress come farebbe un provider che sa il fatto suo: PHP 8.3.35 con OPcache e JIT attivi, object cache Redis via socket, MariaDB e PHP-FPM dietro nginx, con il nuovo archivio ordini di WooCommerce (HPOS) acceso. Cronometriamo una pagina solo dopo aver verificato che WordPress e BookPress mostrino la stessa pagina: stesso markup Elementor, stessa pagina prodotto, stesso catalogo del negozio.

WordPress è misurato senza cache delle pagine, e controlliamo che sia spenta prima di cronometrare: una pagina che una cache può servire la serve la cache su entrambi gli stack, e non misura il motore. Ogni numero qui sotto è WordPress che esegue PHP, il caso in cui finiscono sempre un carrello, una ricerca o una sessione con login.

I server

Abbiamo usato due server Google Cloud che chiunque può affittare e verificare. Il server Intel è una c2-standard-4 da 4 vCPU (Intel Xeon a 3,10 GHz, 2 core fisici con due thread ciascuno, 16 GB di RAM). Il server ARM è una c4a-standard-4 da 4 vCPU (Google Axion, 4 core fisici, 16 GB di RAM). Entrambi girano su Debian 12, e BookPress è compilato allo stesso modo su tutti e due.

Tenga a mente i due conteggi dei core prima di leggere qualsiasi numero. «4 vCPU» è una quantità di hardware diversa su ogni famiglia, quindi un numero ARM lo confrontiamo solo con un WordPress che gira sullo stesso server.

Il risultato: più richieste al secondo su tutti e due i server

Abbiamo spinto ogni motore al massimo di richieste al secondo che regge con il 99% sotto il secondo e zero errori. Su pagine vere di un negozio BookPress serve circa 4,5 volte le richieste al secondo del WordPress ottimizzato sul server Intel, e oltre 5 volte sul server ARM. Ogni valore qui sotto è BookPress contro WordPress sullo stesso server.

PaginaServerRichieste / secondoTempo di risposta p50Tempo di risposta p99
Pagina Elementor Intel 4,53×162 contro 36 richieste/s 3,80× 1,93×
Negozio WooCommerce Intel 4,85×134 contro 28 richieste/s 4,75× 2,79×
Pagina Elementor ARM 5,30×376 contro 71 richieste/s 5,30× 3,70×
Negozio WooCommerce ARM 5,19×297 contro 57 richieste/s 5,20× 2,50×

Misurato su Google Cloud c2-standard-4 (Intel) e c4a-standard-4 (Arm), pagine dinamiche senza cache, BookPress 0.2.64 (il pacchetto che installa lei) contro WordPress 7.1.3 / PHP 8.3.35 con nginx, PHP-FPM, object cache Redis, OPcache con JIT e MariaDB.

Le richieste al secondo sono quelle di ciascun motore al proprio punto di saturazione; p50 e p99 sono i multipli del tempo di risposta mediano e al 99º percentile al punto di saturazione di WordPress, stessa concorrenza per entrambi. WordPress è misurato senza cache delle pagine.

Le pagine di un negozio sono in gran parte il PHP del plugin stesso: sono il caso più difficile. A differenza di una pagina senza plugin, non si possono servire senza eseguire quel PHP. BookPress lo esegue sul proprio motore PHP, che su queste pagine tiene il passo di PHP 8.3.35 con il JIT, o lo supera. Queste pagine erano il nostro punto debole; oggi BookPress è in testa anche lì.

Un sito senza plugin non esegue nessun interprete PHP. Lì BookPress serve 112,9 volte le richieste al secondo di WordPress sul server Intel (5.234 contro 46) e 125 volte sul server ARM (11.436 contro 91), senza plugin installati.

La cache delle pagine è un altro livello

Una cache delle pagine serve HTML già pronto senza generare nulla, su WordPress come su BookPress. Un hit della cache, quindi, non misura nessuno dei due motori. Ogni valore su questo sito è una pagina dinamica generata senza cache sui due stack.

Alcuni temi PHP classici. I template classici di WordPress sono più leggeri dei temi a blocchi. Il rendering dei temi classici in BookPress è più recente del percorso per i temi a blocchi, e alcuni della ventina di temi classici inclusi finiscono ancora in errore. La correzione è in roadmap. Le pagine del negozio qui sopra sono temi a blocchi.

Memoria

La memoria è una misurazione a parte, precedente, fatta su BookPress 0.2.57. L'abbiamo rilevata su entrambi i server dopo una prova a pieno carico, sullo stesso sito con tutti i plugin attivi, contando una volta sola la memoria condivisa fra processi.

Sotto carico, quattro worker BookPress usavano circa 0,6 GB: più o meno quanto un WordPress dimensionato a misura (8 processi figli PHP, 0,55 GB), che serve meno pagine, e un terzo di un pool ottimizzato da 64 processi figli (1,8 GB). Trenta secondi dopo la fine del carico BookPress era sceso a circa 0,3 GB. WordPress tratteneva 0,43 GB (8 processi figli) o 1,8 GB (64 processi figli).

I worker caricano il codice del motore e il bytecode dei plugin una volta sola e li condividono. Ogni worker in più aggiunge il proprio working set sotto carico e ne restituisce la maggior parte a riposo. Un worker fermo da 30 secondi restituisce la memoria al sistema, e il valore a riposo scende. Un pool WordPress si tiene quello che ha preallocato, occupato o fermo che sia. I valori di memoria vengono da BookPress 0.2.57, 13 ottobre 2026; la prova di throughput qui sopra è una misurazione successiva e separata.

Niente object cache, niente server di database, niente cache delle pagine

I provider di hosting WordPress impilano questi livelli per evitare che PHP faccia il lavoro due volte. Ogni lettura dall'object cache è un'andata e ritorno verso Redis più una decodifica in PHP. Un server di database è un altro viaggio. Una cache delle pagine conserva una copia già generata, così nginx risponde senza entrare nello stack.

BookPress non ha nessuno dei tre. Lo storage è integrato e in-process, quindi non c'è nessun viaggio da risparmiare. Non c'è nessuna copia generata da conservare, perché generare la pagina da zero è già la strada più veloce. Una CDN resta utile per i soliti motivi: la distanza dai visitatori e i file statici.

Ogni livello può essere configurato male, finire la memoria, servire contenuti vecchi o chiedere uno svuotamento dopo un deploy. BookPress non ha nessuna di queste parti in movimento. Conta prima di tutto per chi gestisce il server, e poi per la velocità.

Un risultato gioca contro di noi. Se un provider ha già un object cache Redis, lo lasciamo installato: spegnerlo per far bella figura nei numeri sarebbe scorretto. Il nostro motore per i plugin attiva il plugin e il sito viene servito, ma il plugin non riesce a fare il suo lavoro: il motore PHP di BookPress non gli dà il client Redis né le chiamate di rete a basso livello che gli servono. Il plugin ripiega sulla cache per richiesta di WordPress e non conserva nulla fra una richiesta e l'altra. Attivare un plugin qualsiasi vuol dire che il sito esegue PHP a ogni richiesta, quindi un object cache acceso rallenta parecchio una pagina senza plugin e non dà nulla in cambio. BookPress non può eseguire la funzione di questo plugin. Non è la stessa cosa che non averne bisogno. Non installi un object cache su BookPress: le costa e non le rende.

Cosa fa una cache delle pagine, e cosa non può fare

Con una cache delle pagine davanti, in questo benchmark WordPress ha servito decine di migliaia di richieste al secondo, molto più di BookPress. Il numero è vero. È nginx che restituisce un file dal disco, senza nessun PHP in esecuzione.

Una cache delle pagine si ferma dove finisce il suo permesso. Non serve un carrello, un checkout, la pagina dell'account, niente che porti un cookie di sessione, niente con una query string, niente per un visitatore con login. Sono quelle pagine a decidere quanto regge un negozio. Lì la cache si fa da parte e la richiesta arriva al PHP che aveva davanti. Ogni valore di questa pagina misura quel caso.

Il WordPress con cui ci siamo confrontati, per intero

È WordPress 7.1.3 su PHP 8.3.35-FPM, messo a punto come lo mette a punto un provider che sa il fatto suo: OPcache dimensionato perché nulla venga scartato, con il JIT acceso, object cache Redis via socket già caldo, MariaDB con un buffer pool adeguato e WooCommerce sul nuovo archivio ordini (HPOS). Lo abbiamo fatto girare in due pool, così la dimensione del pool non falsa il confronto: un pool ottimizzato (statico da 64 processi figli) e un pool dimensionato a misura (dinamico da 8 processi figli).

Configurazione esatta
  • OPcache con il JIT acceso. 512 MB di codice compilato, un buffer di 64 MB per le stringhe internate, un limite di 100.000 file, validazione dei timestamp spenta e un buffer JIT da 256 MB.
  • Un object cache Redis (Redis 7) via socket UNIX, con il drop-in object-cache installato e la cache calda.
  • MariaDB 11 con un buffer pool InnoDB da 4 GB.
  • PHP-FPM dietro nginx 1.27. Un pool statico da 64 processi figli e un pool dimensionato a misura (dinamico da 8 processi figli), misurati entrambi.
  • WooCommerce su HPOS, il suo nuovo archivio ordini.

I plugin sono nelle versioni della demo: WooCommerce 11.0.1, Elementor 4.2.3, Yoast SEO 28.3 e Contact Form 7 6.1.7, sul tema Kadence 1.5.2. Cronometriamo una pagina solo dopo aver verificato che WordPress e BookPress mostrino la stessa pagina: la vetrina Elementor, la pagina prodotto e il catalogo, controllati su entrambi i server.

La configurazione di BookPress, con lo stesso rigore

bookpress --root /srv/sites/<site> --db /srv/sites/<site>/data/site.db \
          --port <port> --workers 4

BookPress gira senza php.ini, senza pool PHP-FPM, senza object cache, senza cache degli opcode, senza cache delle pagine e senza reverse proxy. Ogni numero di BookPress su questa pagina è una pagina generata da zero.

Quale server affittare

Affitti il server Arm: quattro core fisici dove l'Intel ne ha due, circa il 14 per cento in meno di listino, e da circa 2,2 a 2,3 volte le richieste Elementor e WooCommerce al secondo su BookPress 0.2.64.

Prezzo di listino, Google Cloud us-central1 on-demand: c4a-standard-4 131,11 $ al mese contro c2-standard-4 152,43 $.

I conti di un provider

Un provider dimensiona un server sulla memoria. A pieno carico lo stesso sito occupava circa 0,6 GB su quattro worker BookPress (misurato su 0.2.57), contro 0,55 GB di un WordPress dimensionato a misura e 1,8 GB di un pool ottimizzato da 64 processi figli. A riposo BookPress restituisce la memoria; i pool WordPress no. Quanti siti regge una macchina lo stiamo ancora misurando.

I prezzi li calcoliamo sull'infrastruttura che un provider smette di pagare, cioè proprio quello che i numeri di questa pagina misurano. Vanno da 1,00 $0,85 € per sito al mese con Starter a 0,45 $0,38 € con Agency, e per vCPU oltre i 500 siti. La pagina dei prezzi elenca i piani e mostra come si calcola il valore per il suo parco macchine.

Cosa cambia se gestisce molti siti →