Rendimiento PHP 8: OpCache y JIT explicados
Tu aplicación PHP 8 se siente lenta bajo carga. Has optimizado consultas, añadido caché, pero los tiempos de respuesta siguen rezagados. El culpable podría ser la propia sobrecarga de ejecución de PHP. Dos potentes características—OpCache y JIT—pueden acelerar drásticamente tu código, pero solo si se configuran correctamente. Esta guía explica cómo funcionan y cómo ajustarlas para cargas de trabajo del mundo real.
Qué es OpCache y por qué importa
PHP es un lenguaje interpretado: cada solicitud normalmente analiza y compila tus archivos fuente en bytecode antes de ejecutarse. OpCache almacena ese bytecode compilado en memoria compartida, por lo que las solicitudes posteriores omiten el análisis y la compilación. ¿El resultado? Menor uso de CPU y tiempos de respuesta más rápidos.
OpCache está habilitado por defecto en muchas configuraciones de producción, pero los ajustes predeterminados son conservadores. Ajustarlo puede producir mejoras de rendimiento de 2 a 3 veces para aplicaciones limitadas por CPU.
Directivas clave de configuración de OpCache
- opcache.enable: Establecer en 1 para habilitar. (Predeterminado: 1 en producción, 0 en CLI a menos que se sobrescriba).
- opcache.memory_consumption: Tamaño de memoria compartida en MB. Comienza con 128 MB; aumenta si ves un
opcache.memory_usagealto. - opcache.max_accelerated_files: Número máximo de archivos en caché. Establecer en un número primo mayor que tu total de archivos PHP (por ejemplo, 10007).
- opcache.validate_timestamps: Cuando es 1, PHP verifica las marcas de tiempo de los archivos en busca de cambios. Establecer en 0 en producción para evitar llamadas stat; debes limpiar manualmente la caché después de los despliegues.
- opcache.revalidate_freq: Con qué frecuencia (en segundos) verificar las marcas de tiempo si validate_timestamps=1. Establecer en 0 para desarrollo, 60+ para producción.
- opcache.interned_strings_buffer: Memoria para cadenas internadas (MB). Aumentar a 16 o 32 para aplicaciones grandes.
- opcache.fast_shutdown: Obsoleto en PHP 7.2+, eliminado en PHP 8.0. Ignorar.
- opcache.preload: Ruta a un script de precarga (PHP 7.4+). La precarga compila y almacena en caché archivos al inicio, eliminando la sobrecarga por solicitud para clases críticas.
Configuración recomendada de OpCache para producción
; php.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.interned_strings_buffer=32
opcache.preload=/path/to/preload.php
opcache.preload_user=www-data
Después de cambiar la configuración, reinicia PHP-FPM. Monitorea con opcache_get_status() para verificar la tasa de aciertos y el uso de memoria.
Entendiendo JIT en PHP 8
La compilación JIT (Just-In-Time) lleva OpCache un paso más allá: compila bytecode en código máquina nativo en tiempo de ejecución. Esto puede acelerar significativamente tareas intensivas en CPU como cálculos matemáticos, pero hace poco por las solicitudes web típicas dominadas por E/S (base de datos, sistema de archivos, red).
JIT es parte de OpCache, por lo que primero debes habilitar OpCache. En PHP 8, JIT se configura mediante opcache.jit y opcache.jit_buffer_size.
Directivas de configuración de JIT
- opcache.jit: Controla el modo JIT. Usa
tracing(predeterminado) ofunction. El valor es un código CRTO de 4 dígitos:CRTOdonde C=optimización específica de CPU, R=asignación de registros, T=disparador, O=nivel de optimización. Para la mayoría de las aplicaciones,opcache.jit=tracingestá bien. - opcache.jit_buffer_size: Memoria para código JIT en bytes. Comienza con 64M o 128M. Si se establece en 0, JIT está deshabilitado.
- opcache.jit_hot_loop, opcache.jit_hot_func, opcache.jit_hot_return, opcache.jit_hot_side_exit: Umbrales para la detección de código caliente. Los valores predeterminados suelen estar bien.
Configuración recomendada de JIT
opcache.jit=tracing
opcache.jit_buffer_size=128M
Nota: JIT solo funciona con OpCache habilitado. En CLI, es posible que necesites establecer opcache.enable_cli=1 para probar JIT.
OpCache vs JIT: cuándo usar cuál
| Característica | OpCache | JIT |
|---|---|---|
| Beneficio principal | Almacena en caché bytecode compilado | Compila bytecode a código nativo |
| Mejor para | Todas las aplicaciones PHP | Scripts intensivos en CPU y de larga duración |
| Impacto en aplicaciones limitadas por E/S | Alto (reduce análisis/compilación) | Bajo o nulo |
| Sobrecarga de memoria | Moderada | Búfer adicional |
| Complejidad | Baja | Media |
Guía de ajuste paso a paso
- Habilita OpCache con la configuración recomendada anterior.
- Monitorea OpCache usando
opcache_get_status()o herramientas como OpCache GUI. Apunta a una tasa de aciertos superior al 99%. - Ajusta la memoria si
opcache.memory_usageestá cerca del límite. - Considera la precarga para frameworks grandes (Laravel, Symfony). Crea un script de precarga que requiera las clases de uso frecuente.
- Habilita JIT solo si tu aplicación está limitada por CPU. Prueba con y sin JIT para medir el impacto.
- Realiza benchmarks usando herramientas como
ab,wrkosiege. Compara solicitudes por segundo y latencia. - Despliega cambios gradualmente y monitorea los registros de errores en busca de problemas.
Errores comunes y buenas prácticas
- No deshabilites validate_timestamps en desarrollo: Perderás tiempo preguntándote por qué los cambios de código no surten efecto.
- Limpia OpCache al desplegar: Si validate_timestamps=0, debes restablecer OpCache (por ejemplo, reiniciando PHP-FPM o llamando a
opcache_reset()). - JIT no es una bala de plata: Para aplicaciones CRUD típicas, OpCache por sí solo proporciona la mayoría de las ganancias.
- Vigila la memoria: El búfer JIT y la memoria de OpCache se suman al consumo de PHP. Asegúrate de que tu servidor tenga suficiente RAM.
- Usa la precarga con cuidado: Los archivos precargados siempre están en memoria; evita precargar todo.
Preguntas frecuentes
¿JIT mejora el rendimiento de todas las aplicaciones PHP?
No. JIT beneficia tareas intensivas en CPU como cálculos complejos o procesamiento de datos. Para aplicaciones web limitadas por E/S (consultas a bases de datos, llamadas a API), las ganancias son mínimas. OpCache por sí solo a menudo proporciona la mayor aceleración.
¿Cómo sé si OpCache está funcionando?
Revisa phpinfo() para el estado de OpCache, o llama a opcache_get_status() en un script. Busca opcache_enabled => true y un recuento alto de hits en relación con misses.
¿Puedo usar JIT con PHP 7?
No. JIT se introdujo en PHP 8.0. PHP 7 solo admite OpCache. Si estás en PHP 7, concéntrate en el ajuste de OpCache y considera actualizar a PHP 8 para JIT y otras mejoras de rendimiento.
¿Listo para analizar el rendimiento de tu servidor? Echa un vistazo a nuestro Analizador de Registros de Nginx para obtener información de tus registros de acceso e identificar cuellos de botella.