Rendimiento en aplicaciones web con Symfony2
-
Upload
asier-marques -
Category
Technology
-
view
5.812 -
download
3
description
Transcript of Rendimiento en aplicaciones web con Symfony2
![Page 1: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/1.jpg)
![Page 2: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/2.jpg)
![Page 3: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/3.jpg)
Asier Marqués @asiermarques
Socio fundador de Blackslot.com
Socio fundador de Artesanio.com
Organizador de #webdevbilbao
Arquitecto web, ex-administrador de sistemas Microsoft, apasionado de la creación de servicios en internet y adicto al café.
Escribo en asiermarques.com
![Page 4: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/4.jpg)
Rendimiento Web
![Page 5: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/5.jpg)
El rendimiento importaSegún kissmetrics.com:
El 73% de los usuarios de móvil ha encontrado algún sitio web demasiado lento en cargar.
El 47% de los usuarios esperan un máximo de 2 segundos a que cargue una página web en la que van a comprar algo.
Si un sitio de comercio electrónico está ganando $ 100.000 por día, un retraso de 1 segundo en la página podría costar $ 2.5 millones de perdidas al año.
http://blog.kissmetrics.com/loading-time
![Page 6: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/6.jpg)
Rendimiento no es escalabilidadPero es clave que la aplicación esté bien diseñada y sea escalable.
![Page 7: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/7.jpg)
Cómo diseñar bien
• No te repitas. DRY
• Divide. MVC
• Calidad. TDD
• Symfony2 te ayuda a conseguirlo.
![Page 8: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/8.jpg)
“la optimización prematura es la raíz de todo mal”
Donald Knuth
![Page 9: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/9.jpg)
Antes de optimizar
• No resuelvas problemas que no tienes
• No tomes decisiones tecnológicas en base a lo que hacen “los grandes”
• Monitoriza, estudia la información y después optimiza
• Evita operaciones síncronas que supongan demora
![Page 10: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/10.jpg)
![Page 11: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/11.jpg)
Usa InnoDB!
![Page 12: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/12.jpg)
MyISAM
Bloqueos a nivel de tabla, no de filaLos selects pesados bloquean la tabla frente a escrituraLas escrituras bloquean la tablaLOW_PRIORITY, HIGH_PRIORITYhttp://dev.mysql.com/doc/refman/5.0/en/table-locking.html
No soporta transacciones
No es relacional
![Page 13: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/13.jpg)
InnoDB
Relacional
Bloqueos de fila, no de tabla
Soporta transacciones• Doctrine2 hace uso interno de
transacciones
![Page 14: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/14.jpg)
Configuración
Innodb_buffer_pool_size
Innodb_log_file_size
Innodb_flush_log_at_trx_commit=2
innodb_flush_method=O_DIRECT
innodb_file_per_table
![Page 15: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/15.jpg)
Query Cachehttp://dev.mysql.com/doc/refman/5.1/en/query-cache-status-and-maintenance.html
query_cache_type = 1 # 0 desactivada, 1 activada, 2 bajo demandaquery_cache_size = <tamaño de cache>
SHOW STATUS LIKE 'Qcache%';
! -> Qcache_hits: Número de aciertos de la query caché.
! -> Qcache_lowmem_prunes: El número de consultas eliminadas de la cache por falta de memoria disponible.
! -> Qcache_inserts: El número de consultas insertadas a la cache.
![Page 16: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/16.jpg)
![Page 17: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/17.jpg)
El espacio importa
![Page 18: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/18.jpg)
DivideParticionado
Vertical (por columna)Horizontal (por fila)http://mysql.isu.edu.tw/tech-resources/articles/testing-partitions-large-db.html
Mantener los datos de texto opcionales en otra tabla
Configura InnoDB con innodb_file_per_table Cada archivo maneja1) Los datos de la tabla2) Los datos de los índices3) Los MVCC (Multiversioning Concurrency Control) 4) La metainformación de la tabla
Optimize Table reduce la información de cada archivo y reorganiza los índices
![Page 19: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/19.jpg)
Índices
Usa EXPLAIN para saber cuando utilizarlos
NOT NULL cuando sea posibleUna columna indexada que pueda ser NULL ocupa más espacio
Usa el tipo de datos correcto
![Page 20: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/20.jpg)
EXPLAIN <QUERY>
Valores en los que fijarte
typeALL indica que debe recorrerse toda la tabla y debe evitarseINDEX se debe recorrer todo el índice
key y key_lenCuanto menor sea el valor de KeyLen mejorKey te indica el Índice elegido para la consulta
EXTRAEvitar Filesort y tablas temporalesLas tablas temporales aparecen al ordenar resultados o al hacer agrupaciones
![Page 21: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/21.jpg)
Índices y espacio: Tipos de datos
Usa INT en claves primarias como unsigned en lugar de BIGINT.
Usa TINYINT en lugar de INT(1).TINYINT es 1 Byte, INT(1) son 4
Usa BIT para booleanos en lugar de INT(1) o TINYINT
Usa TIMESTAMP en lugar de DATETIMETIMESTAMP son 4 Bytes, DATETIME son 8
![Page 22: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/22.jpg)
Índices y espacio: Tipos de datos
Usa CHAR(num) en lugar de VARCHAR(num) para valores fijos
No uses palabras en ENUM(), usa un solo carácter si es posible
Usa unsigned INT para guardar ips, no varchar
Usa utf8 cuando sea realmente necesarioVarchar(255) en utf8 son más de 700 bytes
![Page 23: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/23.jpg)
Conoce tus consultas
Es peor tener 83 consultas simples que una consulta “compleja”
No hagas operaciones matemáticas en tus consultas
Aligera en la medida de lo posible tus consultas
No hagas JOINs en campos que no tengan índice
Cuidado con los count y los order
![Page 24: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/24.jpg)
Conoce tus consultas
Count(*)Usa mejor SQL_CALC_FOUND_ROWS
OrderByfilesort en la mayoría de los casosrecupera los PK en una consulta simple antes de hacer una consulta compleja
![Page 25: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/25.jpg)
Ejemplo típico en doctrine
Es típico hacer consultas innecesarias dentro de un bucle.
Tomemos por ejemplo la aplicación de #desymfony
![Page 26: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/26.jpg)
Vista de PonentesSe ejecuta el siguiente dql en el controlador
SELECT p FROM Desymfony\DesymfonyBundle\Entity\Ponente pORDER BY p.nombre ASC
Y en la vista se hace
{% for ponente in ponentes %} … {% for ponencia in ponente.ponencias %}
![Page 27: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/27.jpg)
Resultado
Cada iteración de Ponente hace una query de Ponencias
Tenemos 13 ponentes, se ejecutan 13 querys
Con 200 ponentes, se ejecutarían 200 querys
![Page 28: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/28.jpg)
La solución es sencilla
En el DQL
SELECT p, po FROM Desymfony\DesymfonyBundle\Entity\Ponente p INNER JOIN p.ponencias po ORDER BY p.nombre ASC
Solamente con añadir el INNER JOIN reducimos el número de querys a tan sólo una en lugar de 13 o (n).
![Page 29: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/29.jpg)
Symfony y Doctrine
Usar arrays en las vistas en lugar de objetos
Usar la cache de doctrineCache de DQL$config->setMetadataCacheImpl(new Doctrine\Common\Cache\ApcCache());
Cache de resultados$config->setQueryCacheImpl(new Doctrine\Common\Cache\ApcCache());
![Page 30: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/30.jpg)
Búsqueda
InnoDB no soporta FULLTEXT
Sphinx, Lucene, SolrBuenas opciones incluso para reducir complejidad en consultas, pe. Ordenar, filtros complejos..
![Page 31: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/31.jpg)
Analiza
Debes llevar un control de lo que sucede a diario en tu servidor y comparar los valores que obtengas cuando este tenga problemas con tus valores normales.
Herramientas: Munin, Nagios, Cacti..
![Page 32: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/32.jpg)
Analiza mysqladmin extended
Threads_runningNúmero de consultas que se están ejecutando.
Handler_read_rnd_next y Handler_read_firstSi es muy superior a lo normal puede que sea debido a un problema con los índices.
Handler_rollback El número de rollbacks que se han hecho.
Select_full_joinJoins sin índices, debe ser cero.
Slow_queriesSi este valor crece indica problemas en el rendimiento de la aplicación.
![Page 33: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/33.jpg)
AnalizaSHOW FULL PROCESS LIST\G
Para saber cuánto tardan las consultas pesadas en ejecutarse y las que se encuentran en estado “Locked”
SHOW TABLE STATUS FROM <base datos> LIKE ‘<nombre>’\GComprobar el espacio de la tabla (el Max_data_length nunca puede ser consumido por completo)
EXPLAIN [EXTENDED] <query>
SHOW INNODB STATUS\GEstadísticas de acceso a disco, transacciones, consultas con problemas de integridad..
SHOW PROFILE Comprobar los recursos de hardware consumidos por una queryhttp://dev.mysql.com/doc/refman/5.0/en/show-profiles.html
![Page 34: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/34.jpg)
NO SQL
No lo uses por moda, conoce la tecnología y los problemas que solventaConoce sus posibilidades de escaladoConoce su rendimientoConoce sus posibilidades de backup/restore!
Funciona bien como frontend de una base relacional si su motor es rápido
Buena alternativa a desnormalizar
![Page 35: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/35.jpg)
Cache
![Page 36: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/36.jpg)
Http Cache – RFC 2616
Symfony2 implementa la cache definida en el RFC
Sigue los conceptos Expiración-Validación
Symfony2 tiene su propio proxy cache pero permite ser integrado con sistemas proxy cache como Varnish.
![Page 37: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/37.jpg)
Cache-Control
PublicTodos los usuarios comparten la cache
PrivateLa cache es distinta para cada usuario
No-CacheNo se cachea en ningún casoEn Symfony2 por defecto es no-cache o private
![Page 38: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/38.jpg)
Expires y Cache-Control: max-age
expires (fecha GMT)Frescura = expires – fecha actual
max-age (segundos)s-maxage se usa por servidores proxy, es público por lo que es común a todos los usuarios
max-age tiene prioridad sobre Expires ..y s-maxage sobre el max-age si es pública
![Page 39: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/39.jpg)
expires y max-age en Symfony2
$response = $this ->render('DesymfonyBundle:Ponente:index.html.twig', array('ponentes' => $ponentes)); $response->setPublic(); $response->setMaxAge(10); <- Private $response->setSharedMaxAge(10); <- Public
$date = new DateTime(); $date->modify('+60 seconds');
$response->setExpires($date); <- Private (si no hay un setPublic())
return $response;
![Page 40: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/40.jpg)
expires y max-age en Symfony2
Primera carga de la página, 234ms
Carga desde la caché, 3ms
![Page 41: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/41.jpg)
Validación: Last Modified y ETAG
Last ModifiedFecha de última modificación del archivo, si el servidor retorna una fecha menor a la de la caché del cliente, descargará el archivo.
EtagEl navegador cachea el archivo identificándolo con el valor del Etag.
El navegador comprobará si debe servir el archivo comparando el Etag del servidor con el valor que él tiene almacenado en su cache, para ello usará el campo If-None-Match
![Page 42: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/42.jpg)
Last Modified y ETAG en Symfony2
//debemos crear los métodos en la entidad$etag = $entity->getCurrentETag();$mod_date = $entity->getLastModification();
$response->setETag($etag);$response->setLastModified($mod_date);
if($response->isNotModified($this->get('request'))){ …
![Page 43: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/43.jpg)
Varnish
![Page 44: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/44.jpg)
Varnish
• Proxy cache
• Balanceador de carga
• Lenguaje de configuración VCL
• Soporte para ESI y HTTP Cache
![Page 45: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/45.jpg)
Varnish
Podemos especificar
qué es lo que queremos cachear
Declaramos el servidor o
servidores web frontales
Retornando pass evitamos que se cachee y con lookup
forzamos a que se busque en el cache
![Page 46: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/46.jpg)
VarnishPodemos
indicar un ttl para el objeto en la cache
También podemos evaluar si queremos
cachear desde aquí
![Page 47: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/47.jpg)
Varnish: invalidar cacheIndicamos los Host que pueden lanzar
peticiones de invalidación
Si el request es de tipo PURGE se elimina la
url del host especificado
curl -X PURGE http://dominio.com/url-a-invalidar
![Page 48: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/48.jpg)
Varnish: ESI
![Page 49: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/49.jpg)
Varnish: ESISI una url contiene tags ESI basta con
indicar esi; para que Varnish lo procese
Podemos establecer que si la ruta es /esi/*
le ponga otro ttl o retorne pass, evitando
que se cachee
![Page 50: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/50.jpg)
Varnish con Symfony2
En la plantilla{% render '...:vista' with {}, {'standalone': true} %}Devuelve..<esi:include src=“http://dominio/url_al_contenido”/>
Symfony2 añade automáticamente sólo cuando use ESI un header Surrogate-Control = "abc=ESI/1.0“.
En Varnish le debemos indicar que es capáz de procesar ESI con set req.http.Surrogate-Capability = "abc=ESI/1.0“.http://symfony.com/doc/2.0/cookbook/cache/varnish.html
![Page 51: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/51.jpg)
Más cosas
![Page 52: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/52.jpg)
APC
ByteCode cache para PHP
APC.STAT = 0En producción si no hay cambios frecuentes
![Page 53: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/53.jpg)
Assetic
Agrupa los estáticos indicados de tu sitio web en un único archivo.
Se puede escribir en disco, en un cdn (pe.Amazon s3) o manejar como string.
Comprime y optimiza los css, js e imágenes.
Reduce las peticiones HTTP
Se integra con HTTP Cache de Symfony2 y con la sintaxis de Twig
![Page 54: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/54.jpg)
Assetic
$assets = new AssetCollection( array( new FileAsset(“web/Bundle/style.css”), new GlobAsset(“web/*.css”), )
);$assets->load();
$writer = new AssetWriter(“s3://bucket”);$writer->writeManagerAssets($assets);
![Page 55: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/55.jpg)
Assetic en Symfony2
{% javascripts '@Bundle/Resources/public/js/*' filter=‘nombre_js' %} <script src="{{ asset_url }}"></script> {% endjavascripts %}
$ php app/console assetic:dump s3://bucket
![Page 56: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/56.jpg)
Usa un CDN público
Ahorro de ancho de banda
El navegador probablemente tenga ya cacheadas las librerías comunes (pe. jquery)
![Page 57: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/57.jpg)
Operaciones en tiempo real
El tiempo real no es necesario en la mayoría de los casos.
Envío de emailsProcesamiento de imágenesInvalidaciones de cache
Herramientas: RabbitMQ, Gearman.
Otras soluciones:Queue de SwitfmailerImplementar nuestra solución en memcached, redis..
![Page 58: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/58.jpg)
Usa Html5 y CSS3
![Page 59: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/59.jpg)
Async
![Page 60: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/60.jpg)
Cache Manifest
<html lang="en" manifest=“ejemplo.manifest">
CACHE MANIFEST
CACHEclock.js clock.css
NETWORKno_se_cachea.php
![Page 61: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/61.jpg)
Cache Manifest
El manifiesto se descarga en base a nuestras indicaciones en el HTTP Cache
..o forzándolo con JavaScript mediante el método window.applicationCache
La caché se invalida mediante una comparación byte-for-byte entre el archivo más reciente y el anterior.
![Page 62: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/62.jpg)
No uses imágenes, usa CSS3Border-radius
Gradient
Text-shadow y Box-shadow
Canvas
Font-face
![Page 63: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/63.jpg)
¿Preguntas?
![Page 64: Rendimiento en aplicaciones web con Symfony2](https://reader033.fdocumento.com/reader033/viewer/2022061209/548c9a15b479590a268b461b/html5/thumbnails/64.jpg)
Gracias
Asier MarquésBlackslot
@asiermarqueslinkedin.com/in/[email protected]
Imágeneshttp://www.flickr.com/photos/caharley72/11332057
http://www.flickr.com/photos/poetatum/3457696479
http://www.flickr.com/photos/32299138@N08/5772093221
http://www.flickr.com/photos/aereimilitariorg/3956024476
http://www.flickr.com/photos/zombieite/5181067906
http://www.flickr.com/photos/bcash67/4496036286