Cada vez que PHP ejecuta un script tiene que leerlo, analizarlo y compilarlo a opcodes. OPcache guarda esos opcodes compilados en memoria compartida para que las siguientes peticiones se salten ese trabajo, lo que reduce el uso de CPU y el tiempo de respuesta, sobre todo en frameworks y CMS con cientos o miles de ficheros. En este tutorial ajustarás OPcache para PHP 8.3 con PHP-FPM en Ubuntu 24.04, decidirás cómo se detectan los cambios de código, activarás opcionalmente el JIT y comprobarás con un script que la caché funciona y tiene espacio suficiente.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - PHP 8.3 con PHP-FPM y un servidor web (Nginx o Apache) sirviendo una aplicación PHP.
Paso 1: Comprobar que OPcache está instalado
En Ubuntu 24.04 OPcache se distribuye en el paquete php8.3-opcache, que normalmente ya se instala junto con PHP-FPM. Asegúrate de que está presente:
sudo apt install php8.3-opcache
El paquete activa la extensión con el fichero /etc/php/8.3/mods-available/opcache.ini, enlazado en el directorio de configuración de PHP-FPM:
ls /etc/php/8.3/fpm/conf.d/ | grep opcache
cat /etc/php/8.3/mods-available/opcache.ini
10-opcache.ini
; configuration for php opcache module
; priority=10
zend_extension=opcache.so
opcache.jit=off
OPcache ya está activo para PHP-FPM con los valores por defecto de PHP, que son bastante conservadores: 128 MB de memoria y hasta 10.000 ficheros. Ubuntu además desactiva el JIT de forma explícita con opcache.jit=off.
Nota
php -ien la terminal muestra la configuración de PHP CLI, no la de PHP-FPM. Por eso en el paso 4 comprobarás OPcache directamente contra el proceso PHP-FPM.
Paso 2: Dimensionar la caché para tu aplicación
Hay dos límites que conviene ajustar a tu código:
opcache.max_accelerated_files: número máximo de scripts en caché. Debe ser mayor que el número de ficheros PHP de todas las aplicaciones que sirve el pool.opcache.memory_consumption: memoria compartida en MB para los opcodes.
Cuenta los ficheros PHP de tus aplicaciones (sustituye /var/www si tu código está en otra ruta):
find /var/www -type f -name '*.php' | wc -l
14873
Con unos 15.000 ficheros, un valor de 20000 deja margen. PHP redondea internamente al siguiente número primo de una tabla fija, así que el máximo real que veas después será algo mayor. Para la memoria, 128 MB suele bastar para un WordPress con pocos plugins; 256 MB es un buen punto de partida para Laravel, Symfony, Magento o varias webs en el mismo servidor. En el paso 4 verás cuánta se usa realmente.
Paso 3: Crear un fichero de ajustes de OPcache
En lugar de editar el php.ini principal, crea un fichero propio en conf.d con un prefijo alto para que se cargue después de los del paquete y sus valores tengan prioridad:
sudo nano /etc/php/8.3/fpm/conf.d/99-opcache-tuning.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
; Revisar cambios en los ficheros como máximo cada 2 segundos
opcache.validate_timestamps=1
opcache.revalidate_freq=2
Qué hace cada directiva:
opcache.interned_strings_buffer: memoria en MB para cadenas repetidas (nombres de clases, métodos, claves de arrays) compartidas entre procesos. El valor por defecto es 8; 16 es adecuado para frameworks grandes.opcache.validate_timestamps=1: OPcache comprueba si el fichero ha cambiado en disco y lo recompila si es así.opcache.revalidate_freq=2: esa comprobación se hace como máximo una vez cada 2 segundos por fichero.
Comprueba la sintaxis y recarga PHP-FPM. La recarga también vacía la caché de OPcache:
sudo php-fpm8.3 -t
sudo systemctl reload php8.3-fpm
[25-Sep-2026 12:04:17] NOTICE: configuration file /etc/php/8.3/fpm/php-fpm.conf test is successful
Producción: desactivar la comprobación de cambios
Si despliegas el código de forma controlada (git, CI, rsync) y no editas ficheros a mano en el servidor, puedes evitar que PHP consulte el disco en cada revalidación:
opcache.validate_timestamps=0
Con este valor OPcache nunca detecta cambios por sí solo. Debes recargar PHP-FPM al terminar cada despliegue, o seguirás sirviendo el código antiguo:
sudo systemctl reload php8.3-fpm
Si no controlas cuándo cambia el código (por ejemplo, un WordPress que actualiza plugins desde el panel), mantén opcache.validate_timestamps=1.
Paso 4: Comprobar el estado de OPcache
Para ver la configuración y el uso reales de PHP-FPM, crea un pequeño script fuera del directorio público de la web:
sudo mkdir -p /var/www/tools
sudo nano /var/www/tools/opcache-status.php
<?php
$s = opcache_get_status(false);
$m = $s['memory_usage'];
$st = $s['opcache_statistics'];
printf("OPcache activo: %s\n", $s['opcache_enabled'] ? 'si' : 'no');
printf("Memoria usada: %.1f MB, libre: %.1f MB\n", $m['used_memory'] / 1048576, $m['free_memory'] / 1048576);
printf("Scripts en cache: %d de %d\n", $st['num_cached_scripts'], $st['max_cached_keys']);
printf("Tasa de aciertos: %.2f%%\n", $st['opcache_hit_rate']);
printf("Reinicios por memoria llena: %d\n", $st['oom_restarts']);
printf("JIT: %s (buffer %s)\n", ini_get('opcache.jit'), ini_get('opcache.jit_buffer_size'));
Ejecútalo a través del socket de PHP-FPM con cgi-fcgi, para no tener que publicarlo en el servidor web:
sudo apt install libfcgi-bin
sudo SCRIPT_FILENAME=/var/www/tools/opcache-status.php REQUEST_METHOD=GET cgi-fcgi -bind -connect /run/php/php8.3-fpm.sock
Tras un rato de tráfico real verás algo parecido a esto:
Content-type: text/html; charset=UTF-8
OPcache activo: si
Memoria usada: 142.6 MB, libre: 113.4 MB
Scripts en cache: 9120 de 32531
Tasa de aciertos: 99.87%
Reinicios por memoria llena: 0
JIT: off (buffer 0)
Cómo leerlo:
- Tasa de aciertos: debe estar por encima del 99 % con tráfico estable. Justo después de una recarga será baja hasta que se compilen los scripts.
- Memoria libre: si baja de un 10 % del total o Reinicios por memoria llena es mayor que 0, sube
opcache.memory_consumption. - Scripts en cache: si se acerca al máximo, sube
opcache.max_accelerated_files.
Paso 5: Activar el JIT (opcional)
PHP 8 incluye un compilador JIT que traduce los opcodes más usados a código máquina. Mejora mucho el código de cálculo intensivo (procesamiento de imágenes, algoritmos, scripts matemáticos), pero en aplicaciones web típicas, que pasan la mayor parte del tiempo esperando a la base de datos, la mejora suele ser pequeña. Actívalo solo si tus pruebas muestran una mejora.
Añade estas líneas a /etc/php/8.3/fpm/conf.d/99-opcache-tuning.ini:
opcache.jit=tracing
opcache.jit_buffer_size=64M
El JIT solo funciona si opcache.jit_buffer_size es mayor que 0. Recarga PHP-FPM y vuelve a ejecutar el script de estado:
sudo systemctl reload php8.3-fpm
sudo SCRIPT_FILENAME=/var/www/tools/opcache-status.php REQUEST_METHOD=GET cgi-fcgi -bind -connect /run/php/php8.3-fpm.sock | grep JIT
JIT: tracing (buffer 64M)
Mide el antes y el después con una herramienta como Apache Bench contra una página real de tu aplicación. Si no hay diferencia, vuelve a opcache.jit=off para ahorrar esa memoria.
Paso 6: Medir la mejora
Para confirmar el efecto de OPcache, compara las peticiones por segundo con la caché activada y desactivada. Instala Apache Bench:
sudo apt install apache2-utils
Lanza 500 peticiones con 10 conexiones concurrentes contra una página PHP de tu aplicación (your_domain):
ab -n 500 -c 10 https://your_domain/
Anota el valor de Requests per second. Después, pon temporalmente opcache.enable=0 en 99-opcache-tuning.ini, recarga PHP-FPM, repite la prueba y vuelve a activarlo. En aplicaciones basadas en frameworks es habitual que las peticiones por segundo se multipliquen por dos o por tres con OPcache activo.
Solución de problemas
- Los cambios de código no aparecen: tienes
opcache.validate_timestamps=0o unrevalidate_freqalto. Recarga PHP-FPM consudo systemctl reload php8.3-fpm. Call to undefined function opcache_get_status(): la extensión no está cargada en PHP-FPM. Comprueba que existe/etc/php/8.3/fpm/conf.d/10-opcache.iniy ejecutasudo phpenmod opcachesi no.- Los ajustes no se aplican: otro fichero de
conf.dcon un número mayor los sobrescribe, o los estás comprobando conphp -i(CLI). Usa siempre el script del paso 4. - Tasa de aciertos baja de forma permanente: la caché se llena y se reinicia. Revisa los reinicios por memoria llena y sube los límites del paso 2.
Conclusión
OPcache está ahora dimensionado para tu código, con una estrategia clara para detectar cambios en cada despliegue y un script que te dice si la caché tiene memoria y capacidad suficientes. Como siguientes pasos, ajusta el tamaño de los pools de PHP-FPM a la memoria disponible, añade una caché de datos con Memcached o Redis y activa la compresión Gzip o Brotli en tu servidor web.
