Optimización de aplicaciones PHP
Por Maikel González Suárez | 2008-03-07 | servidor
Con motivo de la Barcelona PHP Conference #1 se presenta una conferencia por Oriol Jiménez de phpbarcelona.org titulada "Optimización de aplicaciones PHP" la cual la presentamos vía Slideshare:
¿Qué es?
- Optimizar es el proceso de modificar un sistema para que este sea más eficaz
- En aplicaciones web en concreto perseguimos el objetivo de:
- Disminuir el consumo de recursos.
- Aumentar la velocidad de ejecución
"La Web no va!"
- Normalmente nadie se preocupa por el rendimiento hasta que se convierte en un problema, como por la seguridad
- PHP es un lenguaje perfecto para montar startups 2.0 en pocos minutos... pero ¿qué pasa si estas startups acaban funcionando?
- Desarrollar sistemas eficientes debería ser una premisa ante un desarrollo no una solución a un problema
El lado del servidor
- Software servidor
- Sistemas de caché
- Optmizaciones de código (*)
Software servidor “Lo más simple posible”
Configuración Apache I/II
- Desactivar
HostnameLookupsy usar siempre IPs enAllowyDeny. - Desactivar .htaccess con
"AllowOverride None" -
Options FollowSymLinks - Usar un
DirectoryIndexlo más corto posible sin wildcards. - Desactivar
ExtendedStatus(mod_status)
Configuración Apache II/II
- ¿Keepalive or not Keepalive? en todo caso con un timeout bajo (5 segundos).
- Desactivar los logs (mod_log_config) si no los usamos, que se encargue el cliente (Google Analytics).
- Desactivar todos los módulos que no usamos
Configuración PHP I/II
Relacionadas con los recursos del sistema:
-
max_execution_time -
max_input_time memory_limit-
output_buffering
Configuración PHP II/II
- Para aumentar el rendimiento desactivar:
-
register_globals -
magic_quotes_* -
expose_php -
register_argc_argv -
always_populate_raw_post_data
-
- Desactivar el log de errores en producción
Contenido estático I/II
- La combinación Apache+mod_php es una de las mejores y más rápidas para servir contenido dinámico
- Para servir contenido estático existen otras opciones mucho más ligeras:
- Lighhtpd, Boa, Tux, Thttpd, LiteSpeed
Contenido estático II/II
- De todos ellos Tux y Lighttpd son ahora mismo los ganadores en velocidad.
- Lighttpd es la mejor opción por posibilidades de configuración, portabilidad, etc. (incluso para ejecutar PHP vía FastCGI).
- Aunque no se tengan varios servidores es una opción igualmente recomendable
Separar el contenido I/II
Usando directorios (/images, /css, etc.):
- Es lo más común y también lo más costoso de separar
- Podemos hacerlo con mod_rewrite:
RewriteRule ^/(.*.(png|gif|jpg)) http://static/$1 [NC,P,L] RewriteRule ^/(.*) http://dynamic/$1 [P,L]
Separar contenido II/II
Usando subdominios:
- Lo más fácil y eficaz
- Al subdominio se le asigna la IP del servidor de contenido estático
- Se puede usar un mismo servidor con varias tarjetas de red o usando un firewall
Comprimir la salida
Ventajas:
- Reduce el tráfico de red (ancho de banda)
- Reduce el tiempo de carga de la página para los usuarios. La página se reduce hasta 8 veces
Desventajas:
- Aumenta el consumo de CPU dependiendo del nivel de compresión. El nivel 1 ofrece 4X y un consumo aceptable
¿Cómo comprimir?
- Usando el módulo mod_deflate del Apache:
AddOutputFilterByType DEFLATE text/ html text/plain text/xml - Usando PHP:
- Vía PHP.ini:
zlib.output_compression=1 - Cambiando el handler del output buffer:
ob_start(‘ob_gzhandler’);
- Vía PHP.ini:
Cambiar el sesión handler
El manejador de sesiones de PHP por defecto trabaja con disco. Alternativas más rápidas:
- RAM disk del SO.
- Memoria compartida:
- mm
- apc
- memcache
Caché "¿Porqué hacer lo mismo más de una vez?"
Concepto de caché
- Una caché son datos duplicados de otros originales donde los datos originales son costosos de acceder en tiempo y/o recursos
- Las estrellas invitadas:
- APC
- Memcache
- Squid
Usos de la caché
En el desarrollo en PHP normalmente nos interesará guardar en la caché:
- Una página completa para no volver a generarla
- Trozos estáticos de webs semi-dinámicas
- Resultados de consultas a BBDD u otros datos
- El código ya compilado para no volver a procesarlo (*)
¿Dónde guardar la caché?
- Bases de datos (BBDD)
- Disco duro (HD)
- Memoria compartida (SHM)
Memoria compartida
- Memoria accesible por varios procesos simultáneamente con el objetivo de comunicarse
- En nuestro caso permite que varios procesos del Apache accedan a los mismos datos
Configurar la memoria
Para usar correctamente la memoria compartida necesitamos ajustar el SO:
- FreeBSD:
# sysctl kern.ipc.shmmax # sysctl kern.ipc.shmall - Linux:
# cat /proc/sys/kernel/shmmax # cat /proc/sys/kernel/shmall
APC
- Caché de opcode para PHP: No tener que procesar el código PHP en cada petición:
- Ahorra accesos a disco al leer de memoria el código "compilado"
- Ahorra la memoria usada en el procesado del código
- Reduce hasta un 400% el tiempo de respuesta
- Ofrece una API para trabajar con SHM
Configuración del APC I/II
- Activación de la extensión:
extension=apc.so - Directivas destacables del APC:
apc.enabled=1 apc.shm_segments=1 apc.shm_size=128
Configuración del APC II/II
Para controlar que archivos guardamos compilados:
apc.cache_by_default=On
apc.filters=""
apc.max_file_size=1M
apc.stat=1
Usando la API de APC
- Guardar un dato:
apc_store('key',serialize($obj), 3600); - Recuperar un dato:
$result = unserialize(apc_fetch ('key')); - Borrar un dato: apc_delete('key');
Administrar APC I/II
- Tenemos algunas funciones para consultar información del APC:
-
apc_cache_info() -
acp_sma_info()
-
- También dispone de una fantástica administración vía web
Administrar APC II/II
[Imagen]
Memcached
- Es un sistema de caché de objetos en memoria distribuida.
- Pensado originalmente para reducir la carga de BBDD de LiveJournal.
- La cache es accesible desde distintos servidores.
- Sigue una estructura LRU con el añadido de tiempos de expiración.
- (Opcional) Tugela: lo mismo pero contra disco.
Instalación de Memcached
- Iniciamos el servidor:
# memcached -d -m 512 -l 127.0.0.1 -p 11211 -u www - Cargamos la extensión PECL:
extension=memcache.so
Usando memcached I/II
- Conectarse al servidor de caché:
$memcache = new Memcache; $memcache->connect('localhost', 11211) or die ("No se pudo conectar"); - Guardar un objeto en la caché:
$memcache->set('key', $obj, false, 10) or die ("Fallo al guardar"); - Recuperar el objeto:
$result = $memcache->get('key');
Usando memcached II/II
- Las keys como máximo son de 250 carácteres y un dato guardado no puede ocupar más de 1 MB
- Para distribuir la caché entre distintos servidores se ha de implementar un sistema propio
Caché de usuario
- Ventajas:
- Reduce el tráfico de red. No se envía nada al cliente
- No consume recursos de servidor de ningún tipo
- Reduce la latencia. El navegador responde directamente
- La desventaja es que no la controlamos
Headers de caché
Fijar el tiempo de caché deseado:
HTTP 1.0 header('Expires: '.date());-
HTTP 1.1 header('Cache-Control: max- age=3600, must-revalidate');
Caché web vía headers
- Utilizar URLs únicas. Una URL siempre sirve el mismo contenido
- Utilizar librerías comunes de imágenes, css, js, etc
- Minimizar el uso de SSL
- Hacer fácilmente variables los enlaces a elementos:
<script src="http://phpbsd.net/js/ func.js?v=123"></script>
Acelerador web
- Se instalan delante de los servidores web.
- Cachean las peticiones de los usuarios siguiendo las headers HTTP
- Es una de las caches más cómodas para un programador pero también muy peligrosa
- Tenemos varias opciones: Squid, Apache, Lighttpd, Varnish
- Squid es el más anciano y también el más usado (flickr, wikipedia, etc.)
Caché con handler de 404
Se trata de generar archivos .html bajo demanda:
- En el HTML siempre enlazamos archivos con la extensión
.html - El servidor web ha de ejecutar un script en el caso de no encontrar un archivo (404)
- Ese script genera el contenido solicitado
- Las siguientes peticiones accederán directamente al
.html
Usar la caché con 404 I/II
- Configuramos el Apache:
ErrorDocument 404 genera_pagina.php - Mantenimiento de la caché:
# find /web -mtime +1h -print0 | xargs -0 rm -f
Usar la caché con 404 II/II
Añadir el código necesario:
$pagina = array_pop(explode('/',$_SERVER ['REQUEST_URI']));
ob_start();
echo 'hola';$contenido = ob_get_contents();
file_put_contents($pagina,$contenido);
ob_end_flush();
Otras opciones de caché
- Pre-genración de páginas
- Directamente desde PHP guardar a disco, bd, o shm (shmop):
- Mediante el output buffer páginas completas o trozos de ellas
- Variables serializadas con cualquier dato
- PEAR Cache_Lite: serializando a disco cómodamente



Deje su comentario