La nueva extensión OPcache de PHP 5.5

2 de julio de 2013

PHP es un lenguaje de programación interpretado, lo que significa que cada vez que se ejecuta un archivo PHP, primero debe compilarse. Si un archivo no cambia con frecuencia, resulta absurdo perder el tiempo compilando una y otra vez un archivo que no ha cambiado.

Por ese motivo, hace muchos años surgieron sistemas de caché como APC que guardan los archivos compilados y los utilizan mientras el archivo original no cambie. Si activas APC es fácil multiplicar el rendimiento de la aplicación entre 2 y 10 veces sin tocar una sola línea de código.

La versión 5.5 de PHP introduce una nueva caché llamada OPcache y que está destinada a reemplazar a APC. En realidad, OPcache es el nuevo nombre del producto Zend Optimizer+ que la empresa Zend lleva años utilizando en sus servicios. Esto significa que OPcache es un producto maduro y probado en miles de servidores de todo tipo. Además, OPcache es hasta un 20% más rápido que APC en muchas pruebas de rendimiento con aplicaciones PHP típicas (ver pruebas de rendimiento).

Instalando la extensión OPcache

Si utilizas PHP 5.5, OPcache ya está instalado y configurado. Si utilizas PHP 5.2, 5.3 o 5.4, puedes emplear el paquete ZendOpcache de PECL correspondiente a tu versión.

Si ya la tienes instalada y no te aparece dentro de las extensiones activadas, puede que tengas que añadir o descomentar la siguiente línea en tu archivo php.ini:

; en servidores Linux y Mac
zend_extension=/ruta/hasta/la/librería/opcache.so

; en servidores Windows
zend_extension=C:\ruta\hasta\el\archivo\php_opcache.dll

Si además de OPcache utilizas la extensión Xdebug, asegúrate de cargar primero la extensión OPcache dentro de tu archivo de configuración.

Configurando la extensión OPcache

El manual oficial de PHP recomienda la siguiente configuración para la extensión OPcache:

opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.revalidate_freq=60
opcache.fast_shutdown=1

La siguiente tabla explica cada una de estas opciones y también indica su valor por defecto:

Opción Valor inicial Descripción
opcache.enable 1 Activa la extensión. Cambia su valor a 0 para desactivar OPcache
opcache.enable_cli 0 Activa OPcache cuando se ejecuta PHP en la línea de comandos
opcache.memory_consumption 64 Cantidad de memoria en MB que puede consumir la caché de OPcache
opcache.interned_strings_buffer 4 Cantidad de memoria en MB utilizada para guardar cadenas de texto que se pueden calcular en tiempo de compilación en vez de ejecución
opcache.max_accelerated_files 2000 Número máximo de archivos que se compilan. El valor debe estar entre 200 y 100.000
opcache.revalidate_freq 2 Cada cuantos segundos se comprueba si un archivo compilado ha cambiado. Si el valor es 0, se comprueba en cada petición. Para desactivar esta comprobación, utiliza la opción opcache.validate_timestamps
opcache.fast_shutdown 0 Si se activa, la extensión OPcache no libera la memoria ocupada, sino que delega esa tarea en el gestor de memoria del motor Zend de PHP. Activar esta opción mejora el rendimiento, pero la memoria se reserva durante más tiempo

Si comparas la tabla anterior (que muestra los valores por defecto de OPcache) con la configuración que recomiendan en el manual oficial de PHP (mostrada anteriormente), verás que la configuración recomendada es más apropiada para aplicaciones PHP complejas, como por ejemplo las que utilizan frameworks como Symfony y Zend.

Al margen de las recomendaciones anteriores, la mejor configuración siempre es la que se ajusta mejor a tu servidor y tus aplicaciones. No olvides probar diferentes valores para cada opción de configuración y analiza las mejoras o pérdidas de rendimiento que consigues con cada cambio. Así conseguirás llegar a la configuración ideal para tu servidor.

Configuración avanzada

La extensión OPcache tiene muchas otras opciones que puedes configurar. Para aquellos programadores que utilizan frameworks como Symfony y Zend o librerías como Doctrine2, la opción opcache.save_comments es realmente importante.

El valor por defecto de esta opción es 1, lo que significa que se mantienen todos los comentarios del código fuente de los archivos que se compilan. Si cambias su valor a 0, todos los comentarios se eliminan, lo que mejora el rendimiento y reduce significativamente el tamaño de los archivos compilados.

El problema es que si eliminas los comentarios, es posible que estés rompiendo el código de Symfony, Doctrine, PHPUnit y muchas otras aplicaciones que utilizan unos comentarios especiales llamados anotaciones para modificar el comportamiento del código.

Así que si utilizas Symfony, Doctrine, Zend Framework o PHPUnit, asegúrate de tener la opción opcache.save_comments=1 o tu aplicación dejará de funcionar.

Otra opción muy importante es opcache.enable_file_override, cuyo valor inicial es 0. Si cambias su valor a 1, cada vez que en tu aplicación ejecutes las funciones file_exists(), is_file() y is_readable(), se comprueba primero si el archivo que pasas como argumento a las funciones anteriores ha sido cacheado. Esta comprobación puede mejorar el rendimiento, pero a cambio corres el riesgo de estar comprobando archivos cacheados que ya no existen o han cambiado.

La siguiente tabla recoge el resto de opciones disponibles en OPcache. A menos que sepas muy bien lo que estás haciendo, es mejor que no modifiques el valor de estas opciones:

Opción Valor inicial Descripción
opcache.max_wasted_percentage 5 Porcentaje máximo de memoria desperdiciada que se tolera antes de forzar un reinicio de OPcache
opcache.use_cwd 1 Si se activa, OPcache añade el directorio al nombre de cada archivo que cachea, por lo que se reducen las posibles colisiones entre archivos con el mismo nombre
opcache.validate_timestamps 1 Si se activa, los archivos cacheados se comprueban periódicamente para ver si han cambiado. Si se desactiva el rendimiento aumenta muchísmo, pero a cambio debes reiniciar el servidor web o borrar la caché a mano cada vez que cambies un archivo
opcache.revalidate_path 0 Los archivos cacheados con el mismo nombre y el mismo include_path se reutilizan (puede haber problemas con archivos con el mismo nombre pero distinta localización)
opcache.load_comments 1 Si se desactiva, los comentarios del código fuente no se cargan, aunque los archivos cacheados mantengan esos comentarios
opcache.optimization_level 0xffffffff Su formato es el de una máscara de bits que indica cuáles de las diferentes pasadas de OPcache se ejecutan
opcache.inherited_hack 1 Opción válida sólo para PHP 5.2 y qu evita un bug relacionado con la herencia de clases
opcache.dups_fix 0 Activa esta opción si se producen errores de tipo "Cannot redeclare class"
opcache.blacklist_filename '' Ruta donde se encuentra el archivo que indica qué archivos no se deben cachear (puedes indicar directorios enteros e incluso nombres de archivos con asteriscos. Ej: *Repositroy.php)
opcache.max_file_size 0 Máximo tamaño de archivo en bytes que se puede guardar en la caché. El valor 0 indica que no hay límites
opcache.consistency_checks 0 Si es distinto de 0 la consistencia de la caché se comprueba cada N peticiones, donde N es el valor de esta opción
opcache.force_restart_timeout 180 Duranción en segundos del tiempo que se espera hasta reiniciar OPcache en caso de que la caché no responda
opcache.error_log '' Ruta del archivo donde se registrarán los errores que se produzcan
opcache.log_verbosity_level 1 Máximo nivel de errores que se guardan en el log. Por defecto, solamente los errores de tipo fatal y error
opcache.preferred_memory_model '' No toques esta opción si no sabes lo que estás haciendo. Esta opción te permite elegir el tipo de memoria a utilizar entre los siguientes valores: mmap, shm, posix y win32
opcache.protect_memory 0 Opción reservada para la depuración interna de OPcache
opcache.mmap_base null Utilizada solamente para indicar la base de los segmentos de memoria compartida en Windows

Utilizando la configuración de APC en OPcache

Si estás acostumbrado a utilizar la caché APC, la siguiente tabla muestra el equivalente en OPcache de las opciones de configuración más habituales de APC:

APC OPcache
apc.enabled=1 opcache.enable=1
apc.shm_segments=1 y apc.shm_size=128M opcache.memory_consumption=128
apc.num_files_hint=4000 opcache.max_accelerated_files=4000
apc.stat=1 opcache.validate_timestamps=1
apc.max_file_size=2M opcache.max_file_size=2
apc.filters="/var/www/apc.php" opcache.blacklist_filename="/var/www/opcache.txt"

Funciones de OPcache

La extensión OPcache incluye dos funciones muy útiles cuando se utiliza la caché en el servidor de producción. La primera función es opcache_reset() que no admite parámetros y devuelve como resultado un valor booleano. El propósito de esta función es borrar toda la caché de OPcache (equivale a al función apc_clear_cache()).

Si utilizas la opción opcache.validate_timestamps=0 e instalas una nueva versión de tu aplicación en el servidor, los cambios no se tendrán en cuenta hasta que caduquen los archivos cacheados. La solución más drástica suele ser reiniciar el servidor, pero con la función opcache_reset() puedes obtener el mismo resultado de forma más elegante.

La otra opción definida por OPcache es opcache_invalidate(), que no borra toda la memoria caché sino un único archivo cacheado:

// borra el archivo 'index.php' de la caché solamente si es más
// nuevo que el archivo 'index.php' cacheado
opcache_invalidate('index.php');

// borra el archivo 'index.php' de la caché (sin importar
// su fecha de modificación)
opcache_invalidate('index.php', true);