La velocidad de carga de las páginas web viene determinada por muchos factores, pero los más importantes son la combinación de la latencia y el número de recursos a descargar, y por otro lado el ancho de banda y el tamaño de estos recursos. Como programadores, lo único que podemos hacer para disminuir la latencia entre nuestros servidores y nuestros usuarios es colocar los servidores lo más cerca posible de nuestros usuarios, o distribuirlos por todo el planeta si nuestra página web no tiene un uso mayoritario en un solo país. Pero estas soluciones suelen ser muy caras y no están al alcance de todo el mundo.
En la práctica, la latencia y el ancho de banda del usuario lo tendremos que tomar como elementos incontrolables. Como el ancho de banda ha ido creciendo exponencialmente desde hace unos años, este elemento ya no tiene la importancia tan crítica que tenía hace tan solo unos años, y el tiempo de espera debido a la latencia y el número de recursos a descargar ha cobrado más importancia. Veamos pues, en detalle, el proceso de descarga de una página web, y por qué afecta tanto la latencia al tiempo total de descarga.
Cuando el navegador tiene que mostrar una página web nueva, digamos http://www.ejemplo.com/, primero tiene que convertir el nombre del dominio a una dirección IP con la que poder conectar, asi que contacta con los DNS de nuestro ISP para conseguir esta dirección IP. Con la dirección IP en su mano, intenta establecer una conexión TCP con ese servidor, siguiendo el proceso conocido como “three-way handshake”. El navegador envía un paquete SYN y espera pacientemente la respuesta del servidor, que será un paquete SYN + ACK. Cuando el navegador reciba el paquete respuesta del servidor ya puede mandar un paquete ACK de respuesta e inmediatamente lanzar una petición HTTP GET del recurso que nos interesa (en nuestro ejemplo, “/”), a lo que el servidor responderá, por ejemplo, mandando el contenido del fichero “index.html”.
Si el tiempo que tarda un paquete en llegar de nuestro navegador al servidor es de 100 ms, necesitaremos 400 ms debido a la latencia antes de que el navegador consiga el primer byte de contenido real, y ya podemos tener una flamante conexión a 20 Mb/s que no reducirá nada este tiempo de espera. A partir de aquí, y hasta que el navegador termina de recibir “index.html” pasará un tiempo dominado por el tamaño de este fichero y el ancho de banda de que dispongamos. Si “index.html” pesa 100 KB y tenemos una conexión de 4 Mb/s tardará unos (100 * 8) Kb / (4 * 1024) Kb/s * 1.2 = 235 ms. El factor “mágico” de 1.2 tiene cuenta de la sobrecarga típica de datos a enviar debido a la encapsulación de estos datos en paquetes.
Una vez con el contenido del HTML, el navegador procede a interpretarlo y, típicamente, encontrará dentro del HTML referencias a otros recursos, como hojas de estilo CSS, Javascript, imágenes, etc. Para cada uno de estos recursos extra se repite todo el proceso anterior, asi pues si hacemos referencia a 10 recursos, un número muy conservador hoy en día, perderíamos 10 * 400 ms = 4 s extra debido a la latencia.
Afortunadamente el navegador paraleliza estas peticiones, pero para no sobrecargar al servidor no hace más de dos peticiones a la vez al mismo dominio. Mención especial merecen los ficheros Javascript, que no se descargan en paralelo. Si en nuestro HTML no usamos ningún fichero Javascript, los 10 recursos añadirán entonces 10 * 400 ms / 2 = 2 s extra.
¿Cómo podemos “engañar” al navegador para que descargue más ficheros en paralelo de nuestro servidor? Hay un truco muy sencillo, que es crear varios subdominios que apunten al mismo servidor, y dividir el enlace en el HTML a nuestros recursos entre estos subdominios. El navegador empieza a descargar en paralelo un máximo de 2 recursos por subdominio, sobre un máximo de 4 dominios simultáneamente. Haciendo esto el tiempo perdido estableciendo las conexiones TCP y empezando a descargar los recursos será de 0.8 s (400 ms para establecer las primeras 8 conexiones + 400 ms para las 2 últimas conexiones).
Hay una forma aún más sencilla de reducir este tiempo de espera. Si el servidor no cierra la conexión TCP con el cliente en cada petición HTTP, usando KeepAlives, dividimos por dos el efecto de la latencia en cada recurso que se descargue en una conexión ya abierta. El efecto de KeepAlives depende del número de subdominios que tengamos, si lo servimos todo desde el mismo dominio, en lugar de los 4 s anteriores tardaremos 400 ms para establecer las 2 primeras conexiones en paralelo + 200 ms por cada uno de los otros 8 recursos a bajar / 2 (número de recursos que se descargan en paralelo) = 400 + 200 * 4 = 1.2 s. Sobre 4 subdominios tendremos una espera usando KeepAlives de 0.6 s, ya que los 2 últimos recursos se descargan sin necesidad de establecer otra vez la conexión TCP.
Hay que tener en cuenta que en algunos servidores web la activación de KeepAlives tiene un impacto sobre el rendimiento muy significativo. Os recomiendo utilizar un servidor web alternativo, como lighttpd, nginx o cherokee al menos para vuestro contenido estático, con KeepAlives activado.
Un cambio que puede tener un efecto significativo en el tiempo de descarga es concatenar todos los ficheros CSS a descargar en un solo fichero (o 2, uno general al sitio y otro particular a la página), concatenar los ficheros Javascript, e incluso concatenar las imágenes, seleccionando la subimagen a mostrar usando CSS Sprites. Así podremos reducir significativamente el número de recursos a descargar.
Otro de los factores que sorprendentemente puede influir en el tiempo de descarga es el tamaño de las peticiones que hace el navegador. Cuando el navegador le pide al servidor una página, le envía también información extra, como el nombre del navegador, el idioma preferido por el usuario, las cookies, etc. Muchos de estos datos (como las cookies) no suelen influir en el resultado devuelto por el servidor para los ficheros CSS, JS o imágenes, y si nuestras cookies son cross-subdomain podemos evitar que el navegador tenga que mandarlas si colocamos los ficheros estáticos en otro dominio. Yahoo! por ejemplo usa el dominio yimg.com para servir este tipo de ficheros. A pesar de que las cookies son relativamente pequeñas, hemos de recordar que típicamente los usuarios navegan con conexiones asimétricas, donde la velocidad de subida puede ser 50 veces inferior a la velocidad de bajada de datos.
Una vez aplicados estos cambios en nuestras páginas, podremos concentrarnos en la segunda parte de mayor influencia en la velocidad, el tamaño de los recursos a descargar, y las distintas formas en que podemos influenciar la caché del navegador para evitar tener que descargar todo cada vez que un usuario llegue a nuestra página. Pero esa es otra historia de la que hablaremos otro día.
perfecto me parecio muy interesante el informe que dieron =D especialmente por el hecho de ser mas largo que los anteriores.
ReplyDeleteSuerte y sigan asi ;)
Muy interesante. Ya sabemos algo más de Panoramio :)
ReplyDeleteEsperando las siguientes entregas...
El artículo me pareció excelente, esta clase de técnicas y trucos son de mucha utilidad para programadores web
ReplyDeleteExistirá alguna herramienta para medir la latencia ?, con firebug se pueden ver varias cosas de estas pero hasta donde sé la latencia no es una de ellas.
ReplyDeleteAgradezco cualquier info.
Un articulo muy util.
ReplyDeleteUna aportación adicional, dado que HTTP es un protocolo basado en TCP debemos tener en cuenta siempre la formula basica: Ventana_TCP=BW*RTT, ¿que quiere decir esto?
Pues que si por ejemplo tenemos una conexión donde el retardo es muy alto para optimizar las transferencias deberíamos cambiar la ventana de TCP a valores de 1024K por ejemplo.
Pero si este articulo constituye la clase magistral que me diste en el pasado SIMO! ;)
ReplyDeleteUn saludo Joaquín.
Txarly
nvivo.es
Muy bueno, gracias por los truquitos, estan excelentes.
ReplyDeleteinteresante el articulo, servira para aplicar a mis proximos proyectos.
ReplyDeleteSaludos
酒店經紀
ReplyDelete酒店兼差
酒店小姐
禮服店
酒店上班
酒店兼職
酒店打工
假日打工
台北酒店經紀
童裝批發
童裝批發
童裝
童裝
酒店喝酒
暑假打工
寒假打工
酒店
酒店經紀人
酒店現領
酒店經紀爆米花
酒店上班PRETTY GIRL
Gracias por el post, lo tendre en cuenta a futuro
ReplyDelete情趣用品
ReplyDelete情趣
情趣商品
A片
色情
成人網站
成人光碟
成人影片
A片下載
免費A片
成人
色情
色情影片
性愛影片
性愛
成人影城
無碼
A片
AV女優
自拍
偷拍
做愛
色情遊戲
情趣用品
情趣
A片
中古車
二手車
跳蛋
電動按摩棒