{"id":188,"date":"2010-03-02T19:31:00","date_gmt":"2010-03-02T18:31:00","guid":{"rendered":"http:\/\/beta.expertosenti.com\/2010\/03\/mejora-del-rendimiento-en-aplicaciones-facebook\/"},"modified":"2017-04-24T16:48:50","modified_gmt":"2017-04-24T14:48:50","slug":"mejora-del-rendimiento-en-aplicaciones-facebook","status":"publish","type":"post","link":"https:\/\/www.xpnti.net\/es\/mejora-del-rendimiento-en-aplicaciones-facebook\/","title":{"rendered":"Mejora del rendimiento en aplicaciones Facebook"},"content":{"rendered":"<p>Supongo que no hace falta explicar que es <a href=\"http:\/\/www.facebook.com\/\" target=\"_blank\">Facebook<\/a> ni decir que los \u00faltimos datos p\u00fablicos indican que hay 350 millones de personas que lo usan con m\u00e1s o menos asiduidad, que dicho as\u00ed tampoco es mucho, pero si todo <a href=\"http:\/\/en.wikipedia.org\/wiki\/List_of_countries_by_population\" target=\"_blank\">Estados Unidos s\u00f3lo son 308 millones<\/a>, imag\u00ednate el poder que puede tener alguien con acceso directo a m\u00e1s gente que el pa\u00eds con m\u00e1s poder de la tierra (y defino poder como el impacto que tienen sus decisiones en el resto)<br \/>Vale Facebook es grande, pero la gente se pasa el d\u00eda jugando a las granjas con vaquitas y tal, pues FarmVille tiene m\u00e1s <a href=\"http:\/\/highscalability.com\/blog\/2010\/2\/8\/how-farmville-scales-to-harvest-75-million-players-a-month.html\" target=\"_blank\">de 75 millones de usuarios \u00fanicos mensuales<\/a> que tienen su granjita con sus animalitos y su propia econom\u00eda, <b>m\u00e1s gente que toda Francia<\/b>, pero todos estos tienen una cierta edad, tienen capacidad para gastar y un nivel socio econ\u00f3mico medio-alto.<\/p>\n<p>Bueno despu\u00e9s de toda esta introducci\u00f3n a lo qu\u00e9 iba, la aplicaciones para Facebook tienen una gran capacidad de crecimiento y el rendimiento y escalabilidad de las mismas es cr\u00edtico, as\u00ed que os voy a explicar el caso de <a href=\"http:\/\/apps.facebook.com\/gracias\" target=\"_blank\">Gracias,Amigo!<\/a>,una peque\u00f1a (de momento) aplicaci\u00f3n para Facebook que todav\u00eda est\u00e1 en Beta pero algunos usuarios estaban notando demasiada lentitud.<br \/>Primero de todo es identificar cuales son las m\u00e9tricas m\u00e1s adecuadas para valorar la mejora,instrumentar la aplicaci\u00f3n para qu\u00e9 arroje datos que se puedan analizar y luego entrar a buscar las mejoras.<br \/>En este caso teniamos:<br \/>1) Objetivar la apreciaci\u00f3n del usuario (va lento)<\/p>\n<ul>\n<li>El tiempo desde el click a la aplicaci\u00f3n hasta que esta es usable tarda demasiado<\/li>\n<li>Una vez dentro tengo un rendimiento adecuado<\/li>\n<\/ul>\n<p>2) Instrumentar la aplicaci\u00f3n<\/p>\n<ul>\n<li>Lo primero que hicimos es calcular el tiempo de proceso en el servidor, la forma m\u00e1s f\u00e1cil y escalable es meter al inicio del codigo una variable con la fecha actual y antes de entregar la respuesta (un redirect 302) hacer la diferencia con el tiempo actual y pasar los mili-segundos como par\u00e1metro de la URL destino.<\/li>\n<li>As\u00ed tenemos que no introducimos un cuello de botella adicional (escritura a fichero\/base de datos), tenemos datos de todos los accesos y son visibles mirando los logs de los servidores Web o tambi\u00e9n en Google Analytics!<\/li>\n<\/ul>\n<p>3) Analizar los n\u00fameros y buscar objetivos<\/p>\n<ul>\n<li>Vemos que el tiempo medio de carga se aproxima a los 10 segundos<\/li>\n<li>M\u00e1s o menos un tercio se lo \u00abcome\u00bb Facebook cargando todo el entorno, aqu\u00ed o la mejora pasa porque Facebook optimiza o porque el usuario adquiere m\u00e1s capacidad de proceso ancho de banda<\/li>\n<li>Otra mitad nos la comemos preguntando a Facebook por el grafo social de nuestro usuario utilizando las llamadas de la API<\/li>\n<li>Y el resto es entre cargas de im\u00e1genes, javascripts, style sheets, etc, lo mismo que antes o mejoramos el tama\u00f1o\/distancia hasta el usuario o este se compra algo m\u00e1s r\u00e1pido<\/li>\n<li>Queremos bajar de los 10 segundos hasta los 2 segundos!, reducir el tiempo de carga un 80%<\/li>\n<\/ul>\n<p><span style=\"font-size: x-large;\">Mejorar!<\/span><\/p>\n<p>Vamos primero a lo f\u00e1cil, la gente de Facebook ha activado un sistema para evitar recargar todo el site cuando un usuario accede a una aplicaci\u00f3n, pues activamos<a href=\"http:\/\/wiki.developers.facebook.com\/index.php\/Quick_Transitions\" target=\"_blank\"> QuickTransitions <\/a>y nos cargamos unos 3 segundos de un plumazo (se tiene que ir con cuidado al activarlo, hay cosas que se pueden romper)<\/p>\n<p>Mejora de carga para ficheros est\u00e1ticos y peque\u00f1itos, convertir algunos de ellos en <a href=\"http:\/\/es.debugmodeon.com\/articulo\/css-sprites-que-son-y-como-generarlos-con-un-sencillo-script\" target=\"_blank\">sprites<\/a> y concatenar Javascripts y CSS, aqu\u00ed ganamos poco tiempo pero reducimos la carga en los servidores y es un proyecto que afecta m\u00e1s los dise\u00f1adores de front-end. Tambi\u00e9n deshabilitamos el Output Caching en el IIS 7.5 y activamos expires de 30 minutos para los contenidos est\u00e1ticos con lo que los clicks dentro de la aplicaci\u00f3n ser\u00e1n mucho m\u00e1s \u00e1giles<\/p>\n<p>Y por \u00faltimo llegamos a la parte de la chicha del tiempo gastado, y sobretodo la que nos impide sacar m\u00e1s el provecho a la concurrencia en el server, el thread se queda enganchado demasiado tiempo con lo que seria muy f\u00e1cil encolar peticiones por falta de Threads aunque el servidor tenga un alto % de idle. En el siguiente gr\u00e1fico vemos como algo tan trivial como la velocidad de acceso del usuario puede tener un efecto perverso en las peticiones por segundo que puedan asumir nuestros servidores<\/p>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><a href=\"http:\/\/2.bp.blogspot.com\/_l_7jiNxwrPk\/S41DXhyo02I\/AAAAAAAAAuE\/N873VhFY190\/s1600-h\/EEDC2010.WebScale.png\" imageanchor=\"1\" style=\"margin-left: 1em; margin-right: 1em;\"><img loading=\"lazy\" border=\"0\" height=\"480\" src=\"http:\/\/2.bp.blogspot.com\/_l_7jiNxwrPk\/S41DXhyo02I\/AAAAAAAAAuE\/N873VhFY190\/s640\/EEDC2010.WebScale.png\" width=\"640\" \/><\/a><\/div>\n<p>Gracias a los datos de la instrumentaci\u00f3n de la aplicaci\u00f3n vemos que tocar la Base de Datos (un SQL 2008 con tablas peque\u00f1as) nos aportaria poco, as\u00ed que vamos a ver como mejorar el acceso al API de Facebook teniendo en cuenta que es poco cacheable<\/p>\n<ol>\n<li>Lanzar N Threads adicionales al de ASP.net y que cada uno de ellos haga sus llamadas al API de FB. De esta forma solo tardar\u00e1 lo que tarde el camino cr\u00edtico de llamadas, ya que puede que algunas se tengan que hacer en serie o hacer la petici\u00f3n de forma as\u00edncrona<\/li>\n<li>Optimizar las llamadas al <a href=\"http:\/\/wiki.developers.facebook.com\/index.php\/API\" target=\"_blank\">API<\/a> y en lugar de utilizar las llamadas est\u00e1ndar, utilizar consultas <a href=\"http:\/\/wiki.developers.facebook.com\/index.php\/FQL\" target=\"_blank\">FQL<\/a>, una especie de SQL sobre los datos de Facebook<\/li>\n<\/ol>\n<p><a href=\"http:\/\/www.facebook.com\/apps\/application.php?id=41094267395\" target=\"_blank\">Gracias, Amigo!<\/a> primero crea la sesi\u00f3n contra Facebook, luego pregunta por los datos completos del usuario que est\u00e1 accediendo (para poder conocer su nombre) y por \u00faltimo carga el grafo social mediante dos llamada en serie, primero pregunta por los amigos que est\u00e9n dados de alta en la aplicaci\u00f3n y luego pide los nombres y foto del perfil de cada uno. Visto esto, la opci\u00f3n de lanzar unos Threads nos mejorar\u00eda poco, solo podr\u00edamos paralelizar las peticiones sobre el usuario actual con la de los amigos, que en el fondo son las que gastan tiempo, as\u00ed que reformamos parte del c\u00f3digo y con una sola consulta FQL obtenemos todos los datos necesarios para la aplicaci\u00f3n con lo que hemos pasado de tres llamadas a FB (unos 400 ms entre una cosa y la otra por cabeza) a solo una que adem\u00e1s es mucho m\u00e1s \u00f3ptima ya que en el fondo las llamadas al API son wrappers sobre consultas FQL. Y eso que los servidores est\u00e1n en USA, si estuviesen en el otro lado del charco, la mejora todav\u00eda hubiese sido m\u00e1s importante<\/p>\n<p>As\u00ed que sumando todo lo hecho hemos conseguido pasar de unos 10 segundos de carga a menos de 2 donde gran parte de la mejora se la lleva el hecho de utilizar una sola llamada y encima m\u00e1s eficiente y un peque\u00f1o cambio en la configuraci\u00f3n de c\u00f3mo Facebook trata las peticiones<\/p>\n<p>Saludos!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Supongo que no hace falta explicar que es Facebook ni decir que los \u00faltimos datos p\u00fablicos indican que hay 350 millones de personas que lo usan con m\u00e1s o menos asiduidad, que dicho as\u00ed tampoco es mucho, pero si todo Estados Unidos s\u00f3lo son 308 millones, imag\u00ednate el poder que puede tener alguien con acceso<a href=\"https:\/\/www.xpnti.net\/es\/mejora-del-rendimiento-en-aplicaciones-facebook\/\">[&#8230;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[16,17,18],"tags":[],"_links":{"self":[{"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/posts\/188"}],"collection":[{"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/comments?post=188"}],"version-history":[{"count":1,"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/posts\/188\/revisions"}],"predecessor-version":[{"id":1968,"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/posts\/188\/revisions\/1968"}],"wp:attachment":[{"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/media?parent=188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/categories?post=188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xpnti.net\/es\/wp-json\/wp\/v2\/tags?post=188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}