Zend OPcache: concetto, installazione e configurazione, con i valori di php.ini e la disattivazione di JIT
Zend OPcache è un'estensione di PHP che compila gli script PHP in bytecode e lo salva nella memoria condivisa, così la compilazione viene saltata quando lo stesso file viene eseguito di nuovo. Quando l'attivazione di JIT su un server WordPress con PHP 8.3 ha causato un errore 500 su tutte le pagine, il server è stato ripristinato lasciando OPcache com'era e disattivando solo JIT.
Da PHP 5.5 OPcache è incluso in PHP per impostazione predefinita.
1️⃣ Concetto di Zend OPcache: cache del bytecode
A ogni richiesta uno script PHP attraversa tre fasi: lettura del file, compilazione in bytecode ed esecuzione. Quando OPcache è attivo, dalla seconda richiesta per lo stesso file le prime due fasi spariscono e resta solo l'esecuzione.
La memoria condivisa in cui OPcache salva il bytecode è usata insieme da tutti i worker di PHP-FPM. Se allo stesso PHP-FPM sono collegati più siti, anche gli script di quei siti vengono salvati in un'unica memoria condivisa.
Ciò che OPcache salva è codice PHP compilato, quindi l'esecuzione di PHP e le query al database avvengono comunque a ogni apertura di una pagina. Saltare del tutto l'esecuzione di PHP salvando l'HTML già pronto è compito della cache di pagina.
2️⃣ Verificare l'installazione di PHP OPcache
Per sapere se OPcache è installato, guarda l'ultima riga dell'output di [php -v].
php -vPHP 8.3.22 (cli) (built: Jun 3 2025 17:17:57) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.3.22, Copyright (c) Zend Technologies
with Zend OPcache v8.3.22, Copyright (c), by Zend TechnologiesSe manca l'ultima riga, installalo con dnf. Il pacchetto di solito si chiama php-opcache; se hai installato più versioni di PHP insieme dal repository Remi, al nome si aggiunge la versione, come in php83-php-opcache.
dnf -y install php-opcacheIl pacchetto php-opcache del repository Remi carica l'estensione con la riga [zend_extension=opcache] di [/etc/php.d/10-opcache.ini]. Dopo l'installazione, riavvia PHP-FPM così OPcache si applica anche alle richieste web.
3️⃣ Configurazione di OPcache: valori di php.ini
Le impostazioni di OPcache possono stare in due posti: la sezione [opcache] di [/etc/php.ini] e [/etc/php.d/10-opcache.ini].
php --iniConfiguration File (php.ini) Path: /etc
Loaded Configuration File: /etc/php.ini
Scan for additional .ini files in: /etc/php.d
Additional .ini files parsed: /etc/php.d/10-opcache.ini,I file della cartella php.d vengono letti dopo php.ini, quindi se la stessa voce è scritta in entrambi i posti vale il valore di php.d.
La tabella qui sotto mostra i valori predefiniti di PHP 8.3 e i valori applicati sul server WordPress esaminato.
| Voce | Valore predefinito di PHP 8.3 | Valore applicato | Significato |
|---|---|---|---|
| opcache.enable | 1 | 1 | Attiva OPcache |
| opcache.enable_cli | 0 | 1 | Usato anche da PHP da riga di comando (wp-cli ecc.) |
| opcache.memory_consumption | 128 | 1024 | Memoria condivisa che salva il bytecode (MB) |
| opcache.interned_strings_buffer | 8 | 16 | Memoria che salva una sola volta le stringhe identiche (MB) |
| opcache.max_accelerated_files | 10000 | 10000 | Limite massimo del numero di chiavi che si possono mettere in cache (il limite reale è un numero primo uguale o maggiore di questo valore: 16229 per 10000) |
| opcache.max_wasted_percentage | 5 | 10 | Se la memoria scarseggia e lo spazio sprecato supera questa percentuale, la cache viene svuotata e riavviata |
| opcache.validate_timestamps | 1 | 1 | Controlla se i file sono cambiati |
| opcache.revalidate_freq | 2 | 60 | Ogni quanto si controllano le modifiche ai file (secondi) |
| opcache.jit | tracing | disable | Modalità di JIT (da PHP 8.4 il valore predefinito è disable) |
| opcache.jit_buffer_size | 0 | 0 | Memoria di JIT; con 0 JIT non funziona (da PHP 8.4 il valore predefinito è 64M) |
I valori inseriti nella sezione [opcache] di [/etc/php.ini] sono questi. La dimensione della memoria si sceglie in base alla memoria del server e [opcache.max_accelerated_files] in base al numero di file di WordPress.
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=1024
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=1
opcache.revalidate_freq=60Se inserisci di nuovo una riga [zend_extension] in php.ini, l'estensione viene caricata due volte e compare l'avviso [Cannot load Zend OPcache].
Con [opcache.revalidate_freq] a 60, dopo la modifica di un file PHP il vecchio codice può continuare a essere eseguito per un massimo di 60 secondi.
Su un server WordPress in cui i file PHP cambiano spesso, lascia [opcache.validate_timestamps] a 1 in modo che le modifiche ai file vengano controllate. Lo 0 che la documentazione di Symfony consiglia per i server di produzione è adatto ai server in cui i file PHP cambiano solo quando si distribuisce una nuova versione.
Anche con [opcache.validate_timestamps] a 0, WordPress svuota da solo la cache dei file modificati quando aggiorni dalla schermata di amministrazione. Ma se aggiorni con wp-cli o modifichi i file via SSH, il vecchio codice continua a essere eseguito finché non riavvii PHP-FPM.
4️⃣ Disattivare JIT di OPcache
Il JIT di PHP 8 velocizza i lavori che richiedono molto calcolo alla CPU, quindi ha poco effetto in un'applicazione come WordPress, che gestisce richieste web. Anche nella misurazione con WordPress pubblicata nell'RFC su JIT di PHP, l'esecuzione con JIT attivo ha gestito 326 richieste al secondo e quella con JIT disattivato 315.
Su un server WordPress con PHP 8.3.22 è stato attivato JIT con [opcache.jit=tracing] e [opcache.jit_buffer_size=128M]. Tre giorni dopo, in un giorno in cui un'ondata di richieste ha fatto riavviare più volte i worker di PHP-FPM, si è verificato un errore 500 su tutte le pagine.
Nel registro degli errori è rimasto il messaggio [Allowed memory size of 1073741824 bytes exhausted]. Il [tried to allocate 4295229440 bytes] che lo segue è la registrazione di un tentativo di allocare 4 GB in una volta con un limite di memoria PHP di 1 GB. Dopo aver disattivato JIT, le stesse richieste sono state elaborate normalmente.
JIT si disattiva inserendo le due righe qui sotto in [/etc/php.d/10-opcache.ini]. Anche se in [/etc/php.ini] restano impostazioni di JIT, valgono i valori di questo file.
opcache.jit=disable
opcache.jit_buffer_size=0In PHP 8.3 il valore predefinito di [opcache.jit_buffer_size] è 0, quindi se non lo imposti a parte JIT non funziona. Da PHP 8.4 anche il valore predefinito di [opcache.jit] è disable.
5️⃣ Applicare e verificare la configurazione
Le impostazioni modificate si applicano solo dopo il riavvio di PHP-FPM.
systemctl restart php-fpmDopo il riavvio la memoria condivisa di OPcache viene svuotata e riallocata con le nuove impostazioni.
php -i | grep -E '^opcache\.(enable|memory_consumption|revalidate_freq|validate_timestamps|jit) 'opcache.enable => On => On
opcache.jit => disable => disable
opcache.memory_consumption => 1024 => 1024
opcache.revalidate_freq => 60 => 60
opcache.validate_timestamps => On => OnI valori stampati da [php -i] sono le impostazioni di PHP da riga di comando. Nella famiglia RHEL anche PHP-FPM legge gli stessi file [/etc/php.ini] e [/etc/php.d], quindi i valori coincidono.
Se chiami [opcache_get_status()] dalla riga di comando, gli script in cache risultano 0. PHP da riga di comando crea una nuova memoria condivisa a ogni esecuzione, quindi l'uso di PHP-FPM si controlla mettendo il file qui sotto nella cartella dei documenti web e aprendolo dal browser.
<?php
header('Content-Type: text/plain');
$s = opcache_get_status(false);
print_r($s['memory_usage']);
print_r($s['opcache_statistics']);
print_r($s['interned_strings_usage']);
var_dump($s['cache_full']);Se [cache_full] è true, la memoria condivisa o le chiavi sono piene. Dopo il controllo, elimina subito questo file.
Su un server in cui tre siti WordPress usano lo stesso PHP-FPM, erano in uso 317 MB dei 1024 MB di memoria condivisa. Gli script in cache erano da 3.366 a 4.222 per sito, 11.358 in tutto.
OPcache salva gli script con il percorso reale e, per i file caricati con un percorso relativo, crea un'altra chiave con la directory di lavoro aggiunta, quindi il numero di chiavi supera quello degli script. Con 11.358 script, le chiavi hanno riempito il limite di 16.229 e anche il buffer di stringhe da 16 MB non aveva più spazio libero.
Quando le chiavi sono piene, i nuovi script non vengono messi in cache e sono compilati a ogni richiesta. In 5 minuti e 21 secondi i cache miss sono passati da 18.408 a 36.027, ma il numero di script in cache è rimasto 11.358.
Su un server che gestisce più WordPress o molti plugin, imposta [opcache.max_accelerated_files] con margine in modo che il limite di chiavi non si riempia. Con 20000 il limite reale di chiavi diventa 32.531. Se il buffer di stringhe è pieno, aumenta anche [opcache.interned_strings_buffer].
🔢 FAQ & contenuti consigliati
Cache
Cache: definizione e tutti gli ambiti in cui si usa il caching
Un articolo che divide gli ambiti in cui si usa la cache, compresi OPcache, che salva codice PHP compilato, e la cache di pagina, che salva HTML già pronto.
PHP-FPM
Avviso max_children di php-fpm: trova la causa nei log prima di aumentare i worker
Un articolo su come individuare dai log la causa dell'avviso che compare quando tutti i worker di PHP-FPM che condividono la memoria condivisa di OPcache sono occupati.
PHP-FPM
Cos’è PHP-FPM | Installare e configurare PHP-FPM
Un articolo sull'installazione di PHP-FPM, dentro il quale funziona OPcache, sulla configurazione del pool in www.conf e sul modo di riavviarlo.
ℹ️ Informativa sull'affiliazione
I contenuti di questo sito includono link di affiliazione. Se un visitatore acquista un prodotto o un servizio tramite uno di questi link, il sito riceve una commissione dal venditore. In questo processo l'importo pagato dall'acquirente (durante le promozioni l'importo scende↓) non aumenta. Prezzi, sconti e disponibilità indicati si riferiscono al momento della stesura e possono differire da quelli reali: prima di acquistare verifica sempre presso il venditore. I prodotti vengono scelti e valutati secondo criteri propri, e le commissioni non influiscono sull'ordine di presentazione né sul contenuto delle valutazioni.