Analizador (profiler) de aplicaciones

Hace algún tiempo leí en uno de esos boletines de noticias, que a los desarrolladores nos gusta coleccionar, pero que rara vez leemos, un MVP de algún país que no recuerdo diciendo que Ants Profiler era una herramienta que todo desarrollador debía utilizar. Como su frase me quedó resonando algunas horas, decidí darle una oportunidad a éste producto y ver de qué se trataba. Ya había tenido algunos acercamientos con productos de los calificados como analizadores o profilers. Mi experiencia no es muy amplia. Sólo conozco dos, el analizador de SQL Server, que por lo general no se usa con toda la utilidad con el que fue concebido y el CLR Profiler, ideal para saber donde y cuanta memoria anda circulando. También se puede monitorear el funcionamiento del GC (Garbage Collector) con éste último. Volviendo a Ants profiler, bajé e instalé el demo disponible en el sitio de Red Gate. Después de algunos minutos ya lo estaba usando (es muy, pero muy simple de usar y configurar). La siguiente es una imagen del producto en pleno funcionamiento.



La idea es simple. Uno ejecuta el analizador, luego ejecuta alguna aplicación o sitio web para analizar y al finalizar la ejecución, te entrega los resultados. La información entregada es directa leer. El resultado se debe tomar como el análisis de alguna función específica de la aplicación que estás monitoreando. Se puede ir navegando de función en función hasta llegar a la de más abajo o a las de nivel superior. En la zona superior se muestra la secuencia de ejecución para llegar a la función que estoy revisando (EstadoDocumentoComprador). Luego nos muestra el tiempo de ejecución de esa función (0,121 segundos). En la zona media un listado de las funciones que llamó la función que se está analizando y por ultimo, aunque no menos importante, el código fuente de la función se estamos monitoreando (EstadoDocumentoComprador).Todo esto lo acompaña también la cantidad de veces que se ejecuta cada función, tiempos promedio, como también mínimo y máximo. Con este nivel de información que podemos obtener de nuestra aplicación, sólo me queda adherirme a la frase del MVP, Ants Profiler es una aplicación que todo desarrollador debe utilizar.


Nota: Al analizar una aplicación web, es necesario que Ants baje y suba el servicio de IIS. Esto deben tenerlo en cuenta para que cuando hagan análisis de éste tipo de aplicaciones, le den tiempo al JIT Compiler de compilar el código la primera vez, para que ésta demora en la ejecución no afecte sus resultados.


Patrick.

Botón "atras" del navegador


El botón “Atrás” o “Back” siempre ha dado problemas. Para los usuarios es muy útil, pero para nosotros (los desarrolladores), un problema no menor que puede hacer tambalear cualquier solución web.


Hasta ahora nunca he visto una solución 100% efectiva (tampoco traigo la panacea), y estudiando el porqué se producen los problemas, la única salida “viable” que se ve es la eliminación definitiva del botón, pero sabemos que eso no va a ocurrir.


Muchas soluciones vistas incluyen abrir una nueva ventana con javascript y esconder los botones. Esta funciona bien hasta que el usuario decide mostrar los botones por que a él le gustan. Los que creen que eliminando los botones evitan su funcionamiento, basan sus creencias en que el usuario no es muy diestro con el navegador, suposición a veces correcta y otras no.


El botón back se puede simular de al menos tres formas que yo conozco.


1.- Presionando el botón derecho del Mouse y eligiendo atrás dentro del menú contextual. Muy simple. Claro, alguien puede suprimir con javascript el hecho de que se pueda presionar el botón derecho, pero ahí coartas la libertad de navegación. Detesto esas páginas.


2.- Con BackSpace o retroceso. Muy simple también. Ahora tendrían que no permitir con javascript el presionar BackSpace, cosa que no tiene lógica.


3.- Haciendo Alt + Flecha Izquierda. Esta se la conocen menos personas. Y es difícil que puedan bloquearla.


¿Que hacer entonces ya que claramente debemos vivir con el problema?


Una solución que he escuchado es hacer tu mapa de navegación del sitio y controlar que el usuario no se salga de este y si aplica back, revisar si se salió y redirigirlo nuevamente a la página. El primer problema viene cuando el usuario tiene configurado el browser para que use la versión del caché y no la del servidor (opción por defecto en IE 5.X). Hasta ahí nomás llega la validación ya que nunca supimos desde el servidor si se salio de la ruta.


¿Que hacemos nosotros en mi empresa?


Aprender a vivir con el problema, es decir, preparando tus páginas a que si el usuario hizo back y tienes información que no debiera estar en esa página (variables sesión, etc), redirigirlo manualmente a otra página, algo así como la opción anterior, pero esta no se dispara cuando hace back sino cuando hace algo después de hacer back.


¿Qué otra opción conozco dentro de las cuales me atrevería a recomendar?


He visto una solución “parche”, pero no tiene ninguna elegancia. Consiste en implementar una sentencia de javascript que haga un forward en la página que no quieres que hagan back. Veamos un ejemplo para que quede mas claro.


Si tienes dos páginas, A y B, y el usuario está en A y luego pasa a B, y no quieres que el usuario de B pueda llegar a A con un back, en A agregas una sentencia en el del tipo .


history.forward();


Esto hará que si el usuario hace back en B, al cargar A lo envía hacia B obligatoriamente. Una gracia que tiene es que al momento de cargar A por primera vez, el script no hace nada y no reclama.


No es una solución ideal, pero te puede salvar en algunos casos.


Patrick Mac Kay
Agosto 2004

Paginación de registros V 1.0



Ayer jueves 5 de agosto, luego de una decepcionante charla que presenciamos junto a unos amigos (Leonardo Garcés y Luís Hereira), decidimos ir a pasar los malos ratos vividos al lugar tradicionalmente utilizado para celebrar, el ShopDog de Pedro de Valdivia con Providencia u 11 de septiembre.


La conversación derivó en variados temas, y después de algunas discusiones bizantinas, caímos en la eterna discusión sobre métodos de paginación. Yo presenté el esquema que actualmente utilizamos en IConstruye. 


Nuestro sistema de paginación funciona de la siguiente forma. Es necesario tener un campo identity y utilizar cache. Una consulta a paginar típica tiene los siguientes elementos


Select
      campos
From
      tablas
Where
      cláusulas


La idea consiste en dividir esta consulta en dos consultas, una que ejecute principalmente la parte del where y la segunda que ejecute principalmente la parte del select y los campos.


Con la primera consulta acotamos a una lista de ids (identitys) de los documentos que cumplen con la restricción where (por eso digo que principalmente ejecuta el where), y almacenamos nuestros N ids en un caché. Si consideramos que cada int pesa 4bytes y almacenamos 500 elementos, tenemos 2kilos (mas algunos bytes de estructura y otros) en un caché. No es mucho. Es mejor que almacenar todo en un caché.


Con la segunda consulta, le pedimos una página cualquiera de x registros. Con esto obtengo los x ids moviéndome sobre el arreglo de enteros almacenado en el cache. Con los ids, ejecuto la segunda consulta, que es mucho mas pesada en el select (y liviana en el where), pero como el resultado son sólo los documentos que quiero, se minimiza bastante el trafico de información que no va a ser considerada después. Traigo así SOLO los x registros de la página solicitada. Para cualquier otra página, ya tengo los ids almacenados en el cache así que no es necesario ejecutar la primera consulta.


Luís menciona que mi sistema está representado por la ecuación Y = m*X + b, es decir una recta con pendiente m y que parte en b. Pueden ver la discusión escrita en la servilleta en la imagen asociada. El costo b es el de la consulta 1 (la de los ids) y por cada pagina X se le pondera por un costo m. Yo argumento que m tiende a cero ya que no hay diferencia significante entre la primera y la última página.



Servilleta de la discusión 


Cuando la discusión se torna inútil nuevamente, Luís propone su método de paginación, obtenido desde http://www.winnetmag.com/Article/ArticleID/40505/40505.html.


Este método se basa en dos consultas, una de ellas anidada en la otra. Un seudo SQL sería algo como


SELECT TOP page_size *
FROM table
WHERE primary_key NOT IN
      (SELECT TOP page_size * (page_number – 1) primary_key FROM table WHERE filter_conditions ORDER BY sort_field)
AND filter_criteria
ORDER BY sort_field


El argumento mío no se deja esperar. Siempre haces dos consultas. Su respuesta, buena en todo caso, es que las primeras páginas son muy rápidas de cargar (por que el select anidado da Top 0 para el primer caso) y que el usuario nunca avanza muchas páginas. Es cierto, pero también ocurre a veces que usuarios llegan hasta altas páginas y ya deja de funcionar bien. En IConstruye utilizamos ese mismo sistema durante un tiempo y habían usuarios que llegaban hasta la página 27.


Cuando la página es muy alta, se pone cada vez mas lento. Este sistema es mas parecido a una exponencial. Verán en la imagen la exponencial y su ecuación ex. Interesante es encontrar el punto donde ex se junta con m*x+b.


¿Cual es mejor?. Dependerá de los requerimientos. Probablemente el sistema perfecto sea una mezcla de ambos, tal como existe el HybridDictionary, que tiene un comportamiento dual dependiendo de la cantidad de elementos. También recuerdo dentro de los algoritmos de ordenamiento, donde el QuickSort era muy rápido, pero para pocos elementos era muy lento. Si se hacia un algoritmo hibrido entre QuickSort y BubbleSort (creo que era el otro), para pocos elementos funcionaba bien el Bubble y para muchos, el Quick.