Cargar Javascript sin bloquear

Es sabido que el tag <script> es bloqueante y frena el browser hasta que descarga, compila y ejecuta su contenido, por ende es altamente recomendable poner todos los scripts al final de la pagina para no demorar el rendering de la misma.  Adicionalmente, hay algunas técnicas para cargar de manera asincronica (no bloqueante).

De todos los scripts que he probado y utilizado, el que mejor resultado da en todos los browsers es una suma de los estudios de steve souders y un setTimeout que encontre en la home de google, que es muy importante para IE6.

<script>
setTimeout( function(){
var _s = document.createElement(’script’);
_s.src =’script_and_style.js’;
(document.getElementsByTagName (’head’)[0]
||      document.documentElement).appendChild(_s);
},0);
</script>

Lo mas importante que vi usando esta técnica es que la mejor posición para llamar al script no es el final de la pagina, sino un poco antes para paralelizar la carga del js con el rendering de la página

:)

Posted in performance | Tagged , , , , | Leave a comment

Load ads defered (without blocking)

Load ads defered (without blocking)
Ads’s scripts are evil, most part of them use document.write to create a new script element, and then it load an other script which make an iframe which load other script which make….and finally your page were blocked, not rendering, until ads are loaded.
We solved this problem using a very stupid defer technic. Steps:
make an empty container where ad has to be showed, ej:  <div id=”target”></div>
at bottom page, make second hide container, and put there the ad’s script, ej:  <div id=”src” style=”display:none;”> <script> relocateADS(’target’,’src’); //adsense ej </script> </div>
put relocateADS declaration before src div
relocateAds
This function is very simple, It just show the src div, and set the absolute position of  target to src. This script use jquery, but it is easy to change if you are not loading jquery
The final result: your page will load all content before ads.
:)

Ads’s scripts are evil, most part of them use document.write to create a new script element, and then it load an other script which make an iframe which load other script which make….and finally your page were blocked, not rendering, until ads are loaded.

We solved this problem using a very stupid defer technic. Steps:

  1. make an empty container where ad has to be showed, ej:  <div id=”target”></div>
  2. at bottom page, make second hide container, and put there the ad’s script, ej:  <div id=”src” style=”display:none;”> <script> relocateADS(’target’,’src’); //adsense ej </script> </div>
  3. put relocateADS declaration before src div

relocateAds

This function is very simple, It just show the src div, and set the absolute position of  target to src. This script use jquery, but it is easy to change if you are not loading jquery


/**
 * move all ads dom element from src div to target div now use absolute position
 * to iframe banners
 */
function relocateAds(tgt,src) {
    try{
        //get elements
        var $s = $('#' + src);
        var $t = $('#' + tgt);
        //vars
        var last_pos = 0;
        var last_height = 0;

        //set initial pos and show
        $s.css({position:'absolute'}).show();                   

        /**
         * set interval to check window/components resize
         * on pos change or height change reset
         */
        setInterval(function(){
            var pos = $t.offset();
            if(pos !== last_pos ){
                last_pos = pos;
                $s.css(pos);
            }
            var height = $s.height();
            if(height !== last_height){
                last_height = height;
                $t.css({height:last_height});
            }
        },1000);                

    }catch(e){}

}

The final result: your page will load all content before ads.

:)

Posted in performance | Tagged , , , , , , | 2 Comments

Cargar imagenes a demanda y ganar performance

(The english version)

Escribí un pequeño script basado en jquery para mejorar la performane al cargar una página. La idea es simple, el script hace que la página cargue solo las imagenes que muestra a medida que el usuario hace scroll. Es muuuuy fácil de usar.

Lo único que tenes que hacer es cambiar la url de la imagen a la propiedad longdesc y agregar el class img-ondemand.

Ej: <img src=”foto.jpg” /> ahora debería ser <img src=”" longdesc=”foto.jpg” class=”img-ondemand” />

Aca esta el code los pasos para usarlo:

http://code.google.com/p/jquery-images-ondemand/

Aca tienen un demo online

http://tips.freedev.com.ar/demos/load-images-ondemand.html

Suerte ;)


Posted in performance | Tagged , , , , , | 5 Comments

Images ondemand

This is a very easy technique to improve web page performance by implementing the tip “Make fewer HTTP Requests“. How? By avoiding downloading images that users will never see.

For instance, you can see what happens on firebug when the browser has to download all thumbnails from a popular blog post, which has a lot of comments. It’s clear to see that downloading and rendering each image on those comments consume a lot of client-side time. Moreover, these images also consume a lot of bandwidth.

Another important point is that this kind of pages have a big height and the average user only has 800px of window height. So, what happens whenever a user requests a page, reads something on an interesting banner and decides to click and leave our page: On the one hand,it is always a good thing to get a banner click, but on the other hand, the browser has had to load all images on that page, even when the user never scrolls and sees what things there are behind the first’s 800px. Therefore, I know you are very smart, and now you know that “scroll” is the keyword here.

The technique to avoid the previous situation on our pages comprises two parts: frontend and backend.

The backend problem is to decide what images are shown by default and what images are “hidden” by default. This part of the problem has not a general or common solution which will depend on our backend code. Then we only have to apply a little switch of properties on img tags, and mark this img tags using a css class.

In this example (on php), I define that I want to show 3 firsts comment’s thumbnail images by default:

$counter = 0;

foreach($comments as $comment){

$counter ;

if($counter > 3){

$img = “<img src=’img/pix.gif’ longdesc=’{$comment->thumbnail_url}’ class=’image-ondemand’/>”;

}else{

$img = “<img src=’{$comment->thumbnail_url}’ />”;

}

echo “<div> $img <p>{$comment->content}</p></div>”;

}

The frontent problem is how to detect on the scroll event the browser, and switch the properties on img tags.

In this example, I use jquery:

var images_switched = false;

$(window).scroll(function(){

if(!images_switched){

images_switch = true;

$(’image-ondemand’).each(function(){

$(this).attr(’src’,$(this).attr(’longdesc’));

});

}

});

I think that it is posible to implement this technique by distincts methods, it is just a example.

Enjoy ;)

Posted in performance, webapps | Tagged , , , , , , , | 1 Comment

Tip – Monitoreos de performance, el punto de partida y de fin de cualquier optimización web

Desde hace un tiempo estoy trabajando en varios proyectos de optimización web, sobre todo en abocado al frontend. Y vengo recomendando en este blog algunas coas a tener en cuenta.

Debo decir que mas allá de cual sea la técnica o herramienta que utilicemos para identificar los posibles problemas de performance de nuestro site, y cuales sus posibles soluciones,  lo mas importantes  es tener información REAL que nos da un buen punto de partida, de la performance de nuestro sitio. Y no basta con hace un análisis en un momento desde nuestra PC con YSLOW, lo mas REAL es saber como funciona todo desde otros ambientes (OS, Browser, conexión, país, etc), para eso lo mejor es utilizar algún servicio de monitoreo sobre nuestro site.  Esto nos va a dar la información y estadísticas necesarias para poder ver cual es a lo largo del tiempo el desempeño del site. Y con esa información podremos decidir cuales son los puntos a atacar en el análisis de problemas y en el proceso de optimización, y cual es el verdadero impacto que van a tener.

Adicionalmente, los monitoreos de performance nos permiten definir un nivel de servicio mínimo y disparar alarmas para poder atacar problemas de esta indole.  Por ej: definimos que la url: www.mysite.com/singup, no puede demorar mas de 1.5 seg en contestar. Si el monitor no obtiene una respuesta en ese lapso u obtiene un error, nos da una alarma, por mail o SMS.

Existen 3 tipos de monitoreos de performance que podemos realizar:

  1. Own Server:  mediante cualquier técnica,  server side,  podemos medir el tiempo que tardan nuestro server en responder cada request. Para ello, solo incluímos algún script en nuestro server (de los cientos que hay en internet).  Estos script van a guardar un log en cada request.  Esto se usa mayormente para monitorear cual es la performance de nuestro site (server-side).
  2. Monitoring Service:  Obviamente si nuestro server se cae o tiene alguna falla, el sistema previo no va a funcionar. Por ello lo mas usado actualmente son los servicios de monitoreo. La verdad que existen cientos, solo basta con buscar en google. Estos servicios dan muchas características, se puede usar diferentes protocolos, dan reportes muy lindos, flows de alarmas, y plugins para incluir macros y cookies.  De los que he visto, lo mejor que encontre fue: http://mon.itor.us/  y http://watchmouse.com/   (comenten si ven algo mejor!)
  3. Client-measurement:  Un ejemplo de esto es Jiffy-web , que nos permite incluir en el frontend de nuestro site, un pequeño javascript y podemos agregar las mediciones que nosotros queramos realizar. También trae todo lo necesario server-side, para almacenar esa info y poder analizarla mediante algunos reportes. Lo mejor de esto, es que las mediciones se realizan con los clientes reales, y en ambientes variados. La gente de digg y twitter, usan esto con solo un porcentaje de los request (obviamente no guardan los millones diarios).  Y lo único malo, es que la configuración server-side, no es tan sencilla para cuentas-share y necesita oracle como base de datos.

Por ejemplo, con este sencillo código, podríamos medir el tiempo que demora la carga de un script de tercero:

<script type="text/javascript">
  Jiffy.mark("slowThirdPartyStart");
</script>

<script type="text/javascript" src="http://www.slowsite.com/slow.js"></script>

<script type="text/javascript">
  Jiffy.measure("slowThirdPartyDone", "slowThirdPartyStart");
</script>

Esta solución es end-to-end, y habra que esperar un poco para que sea mysql friendly.

En resumen: Es muy importante tener una visión constante, del uso real de los usuarios sobre el sitio y de la performance del mismo. Y para eso necesitas datos, cuando mas reales mejor… el secreto es tener info, analizarla y pensar que cambiar…  Si estas leyendo esta página sabes el valor que tiene la alta performance en la calidad de un site (google example ;) )

Suerte :)

Posted in performance, webapps | Tagged , , , , , , , | 2 Comments

tip 14 – Optimización de Imagenes

Resumen:

En estos tips vamos a ver las 4 técnicas mas útiles y simples para la optimización de imagenes para una web. Inclusive técnicas con los últimos adelantos de css y los render engine.  Los Tips de performance que vamos a desarrollar son:

  1. Formato, tamaño y compresión adecuada
  2. Convinar en css sprites
  3. Cache para imagenes
  4. Usar CSS Gradients para efectos

El problema:

En el común de los websites o webapps que se desarrollan actualmente, las imagenes son altamente utilizadas, tanto para cuestiones propias de una imagen, como para cuestiones estéticas del site.  Esto hace que mas del 70% del peso de una página sean imagenes, y por ende mas del 70% del tiempo de carga depende de este factor. Asi que no podemos dejar de darle una gran atención a la hora de pensar en la optimización.

Un ejemplo de esto es el diario elpais.es, de los 500k que tiene, 370k son de imágenes. Donde hay exactamente 102 imágenes. Haciendo  un análisis de los tipos y usos de imágenes, se puede ver que las mismas pueden reducirse a 43 con un peso total de 115k. Lo que nos da una ganancia de 255k, mas del 50% del peso total de la página.  Si pensamos que en cada request estamos desperdiciando esa gran cantidad de bandwidth, y eso en nuestro negocio se traduce a $$$. Y peor aún, perdida de calidad de nuestro sitio en la impresión de los usuarios.

De modo que debemos poner mucha atención a la hora de incluir imágenes a nuestro site.  A continuación, técnicas y herramientas para resolver este problema.

…. continuará

Posted in performance | Tagged , , , , , , | Leave a comment

tip 13 – Reducir la cantidad de Ajax Request

tip : utilizar alguna técnica de “Multi Part Ajax Request”

Como ya sabemos, las webapp o website desarrollados con la técnica de ajax tienen muchísimas ventajas en performance y usabilidad sobre las webapps hechas con la clásica arquitectura  request-response.  Pero también es sabido que el costo de cada Request del navegador suele ser el mas caro a la hora de evaluar un loading. Por ende minimizar los request redunda en ventajas de performance.

Mirando en detalle cualquier webapp que tenga un alto porcentaje de ajax (request bajo XHR o XMLHTTPRequest), entendemos que cada acción realizada en la pagina desencadena una gran cantidad XHR request al server.  Por ejemplo: Agregar un dato en el formulario en un clásico List-Detail, generaría al menos 2 request en un diseño clásico. Uno para insertar los datos y otro para obtener el nuevo List.  En mi experiencia en webapps, la mayoría de las acciones desencadenan entre 3 a 4 request. Y observando Gmail, como una clásica webapp en ajax, podemos ver que son mas de 10 los request que generan cada simple acción como enviar un mail.

Al analizar el tiempo que tiene cada request de ajax, donde generalmente la cantidad de datos transmitidos son menores a 1 o 2k, vemos que el 90% del mismo esta en establecer la conexión con el servidor. Con este dato podemos ver facilmente el problema:

Estamos desperdiciando mucho tiempo en establecer las conexiones de multiples XHR Request.

La solución parece evidente, aunque no es algo altamente popular:

Debemos reducir la cantidad de XHR Request, unificando varios request dentro de uno.

De ese modo podemos enviar varios datos y recibir varios datos en un solo request.  Obviamente que empaquetar y desempaquetar varios request tiene un costo. Lo mejor sera encontrar la relación justa entre la cantidad de request y el costo de empaquetado. Y esto varia según el algoritmo que se use.

Recientemente Micah Snyder de Digg Technology ha publicado un post sobre DUI.Stream, que es una librería Javascript que justamente empaqueta varias request de manera transparente. Es el primer trabajo serio que se ve en este sentido. Y podemos observar la gran diferencia performance en esta demo.

Suerte ;)

Posted in performance, webapps | Tagged , , , , | Leave a comment

tip 12 – Como paralelizar el trabajo del cliente y el servidor con “Flush”

Si bien en este blog se trabajo sobre la idea de que la mayor parte de las mejoras que se pueden realizar para optimizar la performance de un web site, no están en el código del servidor. Existen algunos casos que un pequeño truco puede ayudarnos mucho en una página que tiene una demora muy alta en construirse en el servidor. Por ejemplo cuando debe realizarse una consulta muy lenta a una base de datos o bien cuando consultamos un servicio web externo, etc.

En la mayoría de los lenguajes server-side como: PHP, Python, ASP, JSP, Perl, etc ; existe una función para poder hacer un flush del contenido antes de finalizar la ejecución de una página. Que significa esto: que nosotros podemos disponer que en determinado instante, el servidor comience a transmitir el Response del HTTP Request recibido. Esto permite que el browser (el navegador del cliente), empiece a procesar e interpretar el contenido recibido, aún si el servidor sigue procesando el request original.

Por ejemplo,  si tenemos una página web que en la mitad de la misma, el en servidor consulta un servicio web externo para formar un listado, y esto demora mucho. Podemos poner antes de ejecutar esa llamada externa un “flush()” y de ese modo permitir que el servidor web paralelamente envie el contenido generado hasta el momento al cliente. Esto tipicamente es el “header” y parte del “body” donde ya puede contener enlaces a componentes externos como CSS, Imagenes, etc. De ese modo, el browser puede iniciar la descarga de estos componentes, mientras el servidor web continua procesando página. Y asi trabajar en paralelo para reducir al máximo la demora y mejorar notablemente la performance.

El secreto es saber ubicar en el lugar adecuado el Flush, el caso típico es después del header, en otros casos lo he utilizado en algún ciclo donde tenia muchas consultas a servicios web externos,  para ir dando los resultados parcialmente.

Lamentablemete esto no se puede realizar en algunos sistemas de templating como el de Django.

Les dejo un enlace a la docu de Flush en PHP

Suerte :)

Posted in performance, webapps | Tagged , , , , , , | 2 Comments

Videos de Steave Souder en la universidad de Stanford

Les quería dejar el enlace a las tres primeras clases de ” High Performance Web Sites ” en facultad de Computer Science la universidad de Stanford dictadas por el investigador y ahora colaborador de Google Steave Souder.

Los videos aquí

Lamentablemente solo podemos ver las 3 primeras y si queremos ver el resto debemos pagar u$ 600. Otra cosa, para verlos deben tener “Microsoft Silverlight” :(

Espero los disfruten como yo.

Suerte :)

Posted in performance | Tagged , , , , , | Leave a comment

tip 11 – Descargas en paralelo

tip: utilizar entre 2 y 6 hostnames para componentes estaticos (CSS, JS e Img)

Por una especificación de HTTP 1.1 muchos navegadores tienen el limite de descarga de hasta dos componentes en paralelo por hostname. Obviamente esto perjudica la performance de carga de nuestra web. Aunque por suerte en las últimas versiones de Firefox, IE, etc este límite se ha modificado a 6.

Como sabemos, un website o webapp tiene muchos componentes externos al HTML principal, y los mismos deben ser descargados por el navegador ( a menos que esten en cache ). Este costo de descarga es muy facil de reducir si podemos paralelizar la descarga de los mismos.

Ejemplo de como ganar performance maximizando la descargas en paralelo:

Si tenemos un html donde hay 10 imagenes como las siguientes:

<img src=”misitio.com/imagen1.jpg” />
<img src=”misitio.com/imagen2.jpg” />
<img src=”misitio.com/imagen3.jpg” />
<img src=”misitio.com/imagen4.jpg” />
<img src=”misitio.com/imagen5.jpg” />
<img src=”misitio.com/imagen6.jpg” />
<img src=”misitio.com/imagen7.jpg” />
<img src=”misitio.com/imagen8.jpg” />
<img src=”misitio.com/imagen9.jpg” />
<img src=”misitio.com/imagen10.jpg” />


(supongamos que todas tienen el mismo peso 10k, y demoran 1 segundo en descargar para simplificar el ejemplo)

En un navegador estandar demoraría en descargar esas imagenes 5 segundos, ya que solo puede descargar dos a la vez. Pero si cambiamos el numero de hostnames a 2 de esta forma:

<img src=”img1.misitio.com/imagen1.jpg” />
<img src=”img1.misitio.com/imagen2.jpg” />
<img src=”img1.misitio.com/imagen3.jpg” />
<img src=”img1.misitio.com/imagen4.jpg” />
<img src=”img1.misitio.com/imagen5.jpg” />
<img src=”img2.misitio.com/imagen6.jpg” />
<img src=”img2.misitio.com/imagen7.jpg” />
<img src=”img2.misitio.com/imagen8.jpg” />
<img src=”img2.misitio.com/imagen9.jpg” />
<img src=”img2.misitio.com/imagen10.jpg” />


Podríamos bajar el tiempo a 3 segundos. Y si utilizamos un 3 hostname img3.misitio.com, podríamos bajar el tiempo a 2 segundos. Y “en teoría” con 5 hostnames el tiempo de descarga de todas las imagenes sería de 1 segundo.

En realidad cuantos mas hostnames agregamos mas paralelizamos la descarga, pero también esto trae otros costos, como mayor consumo de CPU en el navegador del cliente, mayor consumo del ancho de banda, y sobre todo mayor tiempo en la resolución de los DNS de cada hostname.

Por ende y como explican en este artículo lo mejor es manejar entre 2 y 6 hostnames.

Suerte ;)

Posted in performance | Tagged , , , , , | 4 Comments