[Evento] Depuración y Optimización Avanzada de Aplicaciones

Hola a todos, el próximo jueves 2 de octubre participo en la charla “Depuración y Optimización Avanzada de Aplicaciones” que se celebrará en el CIIN (Centro de innovación de Microsoft de Cantabria) por parte de Plain Concepts, y con mi compañero Pablo Doval.

Por cierto el evento se retransmitirá online a través de la web de Microsoft (el enlace a final del post).

evento-depuracion

Cuando desarrollamos Software, pasamos por una serie de etapas, desde el diseño hasta el despliegue final, en las que buscamos proporcionar soluciones que resuelvan de forma excelente los problemas y requerimientos planteados. Sin embargo, el camino no es fácil y muchas veces nos olvidamos de aspectos muy importantes como son la depuración, la optimización y el testeo de nuestras aplicaciones como camino a lograr aplicaciones con el mayor nivel de calidad posible. Para cubrir esta etapa imprescindible en todo desarrollo de software, os presentamos en colaboración con Plain Concepts una nueva jornada de la que se puede hablar durante días y días: Depuración y Optimización Avanzada de Aplicaciones.

La jornada que os proponemos será gratuita por cortesía de Plain Concepts y constará de un repaso de la depuración básica con Visual Studio, profiling de problemas de rendimiento y depuración avanzada con WinDbg. Se tocarán temas como análisis de rendimiento y pruebas de carga, localización de puntos calientes y cuellos de botella, resolución de problemas esquivos (cuelgues, pérdidas, bloqueos, CTDs…) tanto en vivo como de modo postmortem mediante el análisis de volcados de memoria y otras técnicas de depuración. También se abordarán, durante el transcurso de la sesión, aspectos de soportabilidad como la construcción de un servidor de símbolos sincronizados, la generación de volcados de memoria en nuestras aplicaciones, etc. Como viene siendo habitual, la parte teórica irá acompañada de demostraciones prácticas sobre escenarios habituales de optimización y resolución de problemas.

La jornada será impartida por Pablo Alvarez Doval. Pablo ha estado vinculado a las tecnologías Microsoft desde el inicio de su carrera profesional, y fue miembro del GTSC de Microsoft en el equipo de SQL Server. Actualmente trabaja para Plain Concepts, donde lidera la iniciativa DOT (Debugging & Optimization Team), destinada a ayudar a sus clientes en la resolución de problemas de rendimiento o problemas de difícil trazabilidad. Dispone de un blog en http://geeks.ms/blogs/palvarez, donde aborda principalmente temas de rendimiento, WinDbg y SQL Server.

http://www.ciin.es/web/servicios/eventos/Paginas/DepOptApp021008.aspx?Fecha=02-10-2008 

http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032390753&EventCategory=4&culture=es-ES&CountryCode=ES 

http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032390757&EventCategory=4&culture=es-ES&CountryCode=ES

ResourceDictionary y el soporte para Blend en WPF

La clase ResourceDictionary permite tener un diccionario de recursos para que lo utilicemos en nuestras aplicaciones. Dentro de WPF es normal usar esta clase, ya que como explicamos en otro post anterior (WPF para programadores de Windows Forms 5), estos se pueden sumar o “Merge” con otros diccionarios para tenernos todos centralizados dentro de Application.Current.Resources.

Esta característica para el soporte te temas (Themes) y para tener en un lugar centralizado los recursos de la aplicación es estupendo, pero si alguna vez has hecho un control con soporte para tiempo de diseño, digamos Visual Studio 2008 o Blend, hacer que esto funcione se puede convertir en un infierno. Veamos porque.

Esta clase Application es una clase implementada como un singleton que gestiona el ciclo de vida de una aplicación WPF, únicamente puede haber una instancia por dominio de aplicación. Imaginemos que por un momento tenemos un código parecido a este.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;

namespace ApplicationDesingTime
{
    public class MyCustomControl : ContentControl
    {
        public MyCustomControl()
        {
            Template = (ControlTemplate)App.Current.Resources["Style1"];
        }
    }
}

En el que estamos haciendo un control personalizado que cambia su Template actual para cambiar el árbol visual de controles y tener otro aspecto. Hasta aquí todo bien estamos accediendo al diccionario de recursos que tenemos dentro de nuestra aplicación. Si compilamos y nos llevamos este control que debería de tener este aspecto a blend y lo usamos aparece esto otro.

image

Blend

Esto porque ocurre, si ejecutamos la aplicación funciona perfectamente pero si la visualizamos en Blend resulta que no se visualiza correctamente. Es una lástima que tengamos nuestro control, más o menos complejo, pero no podamos verlo en tiempo de diseño. La clave está en la clase Application. Como antes he comentado la clase Application es única por dominio de aplicación lo que significa que dentro de Blend o Visual Studio existe una clase Application, pero es que resulta que, en el caso de Blend, la clase Application corresponde a la propia aplicación de Blend!!. Esto es un bug o algo así del framework o de Blend, o es que simplemente Blend es un entorno de hosting para nuestros controles y aunque Blend crea instancias de nuestros controles para tiempo de diseño, no es el mismo entorno que cuando se ejecutan.

Y ahora, ¿ya no vamos a tener controles con tiempo de diseño como los que viene con WPF?, claro que sí, pero hay que hacerlo de una manera especial.

Lo primero de todo es que necesitamos alguna manera de saber cuando estamos en blend o cuando estamos ejecutando la aplicación. Esto lo podríamos hacer viendo si el nombre del proceso en el que está mi control es blend.exe, pero si estamos en Visual Studio o en otro programa esto no funcionará, además, WPF tiene una manera más elegante de sabes si estamos en tiempo de diseño o no.

En System.ComponentModel hay una clase System.ComponentModel.DesignerProperties que tiene un método estatico, llamado GetIsInDesignMode que acepta un DependencyObject y te devuelve un booleano que indica si el control está en tiempo de diseño o no. Esto se hace a través de una DependencyProperty atachada que hay en esa clase.

Esta característica también está en Windows Forms, pero a diferencia de Windows Forms, si se consulta esta propiedad en el constructor, esta propiedad está establecida, mientras que en Windows Forms después de crear el objeto el diseñador establece la propiedad de tiempo de diseño.

Ahora que ya sabemos esta información vamos a hacer una clase helper que nos permita acceder a los elementos del ResourceDiccionary desde todos los tiempos.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;

namespace ApplicationDesingTime
{
    public class MyCustomControl : ContentControl
    {
        public MyCustomControl()
        {
            //Template = (ControlTemplate)App.Current.Resources["Ejemplo"];
            Template = TemplateHelper.GetData<ControlTemplate>(this, "Ejemplo");
        }
    }
}

image

Para iniciar un ResourceDictionary hay que establecer la propiedad Source indicando cual es el fichero .xaml que se va a utilizar como origen de datos. Esta propiedad Source es de tipo Uri, en el que hay que establecer el formato de ensamblado y ruta en un formato especial.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;
using System.Diagnostics;

namespace ApplicationDesingTime
{
    public static class TemplateHelper
    {
        private static ResourceDictionary DesingTimeAppDiccionary;

        public static T GetData<T>(DependencyObject context, string name)
        {
            if (DesignerProperties.GetIsInDesignMode(context))
            {
                if (DesingTimeAppDiccionary == null)
                {
                    DesingTimeAppDiccionary = new ResourceDictionary();
                    try
                    {
                        DesingTimeAppDiccionary.Source = new Uri("/ApplicationDesingTime;component/Dictionary1.xaml", UriKind.RelativeOrAbsolute);
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine(ex.ToString());
                    }
                }
                return (T)(object)DesingTimeAppDiccionary[name];
            }
            else
            {
                return (T)(object)App.Current.Resources[name];
            }
        }
    }
}

El formato de la Uri sería algo así.

/{assembly};component/{fichero.xaml}

Espero que esto os sirva en los proyectos de WPF que hagais y si haceis muchos controles con tiempo de diseño es interesante este pequeño truco.

Y por cierto si estais pensando en hacer una clase con xaml y un fichero de codigo trasero, hay que tener en cuenta que después esa clase no puede ser la clase base de otro control que esté compuesto de xaml y un fichero .cs así que esta es la mejor manera de modificar el arbol visual de un control para personalizarlo. Pero de eso hablaremos en otro post.

Codigo fuente del post [ApplicationDesingTime.zip]

ResourceDictionary y el soporte para Blend en WPF

La clase ResourceDictionary permite tener un diccionario de recursos para que lo utilicemos en nuestras aplicaciones. Dentro de WPF es normal usar esta clase, ya que como explicamos en otro post anterior (WPF para programadores de Windows Forms 5), estos se pueden sumar o “Merge” con otros diccionarios para tenernos todos centralizados dentro de Application.Current.Resources.

Esta característica para el soporte te temas (Themes) y para tener en un lugar centralizado los recursos de la aplicación es estupendo, pero si alguna vez has hecho un control con soporte para tiempo de diseño, digamos Visual Studio 2008 o Blend, hacer que esto funcione se puede convertir en un infierno. Veamos porque.

Esta clase Application es una clase implementada como un singleton que gestiona el ciclo de vida de una aplicación WPF, únicamente puede haber una instancia por dominio de aplicación. Imaginemos que por un momento tenemos un código parecido a este.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;

namespace ApplicationDesingTime
{
    public class MyCustomControl : ContentControl
    {
        public MyCustomControl()
        {
            Template = (ControlTemplate)App.Current.Resources["Style1"];
        }
    }
}

En el que estamos haciendo un control personalizado que cambia su Template actual para cambiar el árbol visual de controles y tener otro aspecto. Hasta aquí todo bien estamos accediendo al diccionario de recursos que tenemos dentro de nuestra aplicación. Si compilamos y nos llevamos este control que debería de tener este aspecto a blend y lo usamos aparece esto otro.

image

Blend

Esto porque ocurre, si ejecutamos la aplicación funciona perfectamente pero si la visualizamos en Blend resulta que no se visualiza correctamente. Es una lástima que tengamos nuestro control, más o menos complejo, pero no podamos verlo en tiempo de diseño. La clave está en la clase Application. Como antes he comentado la clase Application es única por dominio de aplicación lo que significa que dentro de Blend o Visual Studio existe una clase Application, pero es que resulta que, en el caso de Blend, la clase Application corresponde a la propia aplicación de Blend!!. Esto es un bug o algo así del framework o de Blend, o es que simplemente Blend es un entorno de hosting para nuestros controles y aunque Blend crea instancias de nuestros controles para tiempo de diseño, no es el mismo entorno que cuando se ejecutan.

Y ahora, ¿ya no vamos a tener controles con tiempo de diseño como los que viene con WPF?, claro que sí, pero hay que hacerlo de una manera especial.

Lo primero de todo es que necesitamos alguna manera de saber cuando estamos en blend o cuando estamos ejecutando la aplicación. Esto lo podríamos hacer viendo si el nombre del proceso en el que está mi control es blend.exe, pero si estamos en Visual Studio o en otro programa esto no funcionará, además, WPF tiene una manera más elegante de sabes si estamos en tiempo de diseño o no.

En System.ComponentModel hay una clase System.ComponentModel.DesignerProperties que tiene un método estatico, llamado GetIsInDesignMode que acepta un DependencyObject y te devuelve un booleano que indica si el control está en tiempo de diseño o no. Esto se hace a través de una DependencyProperty atachada que hay en esa clase.

Esta característica también está en Windows Forms, pero a diferencia de Windows Forms, si se consulta esta propiedad en el constructor, esta propiedad está establecida, mientras que en Windows Forms después de crear el objeto el diseñador establece la propiedad de tiempo de diseño.

Ahora que ya sabemos esta información vamos a hacer una clase helper que nos permita acceder a los elementos del ResourceDiccionary desde todos los tiempos.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;

namespace ApplicationDesingTime
{
    public class MyCustomControl : ContentControl
    {
        public MyCustomControl()
        {
            //Template = (ControlTemplate)App.Current.Resources["Ejemplo"];
            Template = TemplateHelper.GetData<ControlTemplate>(this, "Ejemplo");
        }
    }
}

image

Para iniciar un ResourceDictionary hay que establecer la propiedad Source indicando cual es el fichero .xaml que se va a utilizar como origen de datos. Esta propiedad Source es de tipo Uri, en el que hay que establecer el formato de ensamblado y ruta en un formato especial.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;
using System.Diagnostics;

namespace ApplicationDesingTime
{
    public static class TemplateHelper
    {
        private static ResourceDictionary DesingTimeAppDiccionary;

        public static T GetData<T>(DependencyObject context, string name)
        {
            if (DesignerProperties.GetIsInDesignMode(context))
            {
                if (DesingTimeAppDiccionary == null)
                {
                    DesingTimeAppDiccionary = new ResourceDictionary();
                    try
                    {
                        DesingTimeAppDiccionary.Source = new Uri("/ApplicationDesingTime;component/Dictionary1.xaml", UriKind.RelativeOrAbsolute);
                    }
                    catch (Exception ex)
                    {
                        Trace.WriteLine(ex.ToString());
                    }
                }
                return (T)(object)DesingTimeAppDiccionary[name];
            }
            else
            {
                return (T)(object)App.Current.Resources[name];
            }
        }
    }
}

El formato de la Uri sería algo así.

/{assembly};component/{fichero.xaml}

Espero que esto os sirva en los proyectos de WPF que hagais y si haceis muchos controles con tiempo de diseño es interesante este pequeño truco.

Y por cierto si estais pensando en hacer una clase con xaml y un fichero de codigo trasero, hay que tener en cuenta que después esa clase no puede ser la clase base de otro control que esté compuesto de xaml y un fichero .cs así que esta es la mejor manera de modificar el arbol visual de un control para personalizarlo. Pero de eso hablaremos en otro post.

Google Chrome

No suelo escribir sobre las novedades que la web nos ofrece a menos que sea algo interesante para el programador, pero viendo esto de google chrome no he podido evitarlo. Creo que todo el mundo se ha bajado el navegador en cuestión si no lo ha hecho lo invito.

La primera impresión buena, es un diseño sencillo. Empiezo a navegar y me llevo una sorpresa. Normalmente siempre tengo abierto el process explorer un sustituto del administrador de tareas de windows, y cuando he mirado al árbol de procesos me he llevado una sorpresa muy grande.

 

image

Resulta que el navegador de chrome abre un proceso por cada pestaña, parece que eso de aislar cada tab por si uno falla que falle solo esa pestaña lo han llevado al extremo.

Pero resulta que esto es una muy mala práctica. Como sabréis una de la cosa más costosa para Windows es iniciar un proceso, ya que debido a las características de seguridad y aislamiento Windows genera una memoria virtual para cada proceso además de todas las estructuras necesarias para que el proceso se pueda iniciar. Pues me parece que esta solución de los “ingenieros” de software de google, es la más obvia, cutre y sobre todo la más fácil. Ni que decir tiene que este modelo de navegador hace que se generen muchos procesos, que, por muy ligeros que sean, tienen que cargar sus dll, reservar memoria a Windows y demás tareas. Es como si en la programación de páginas web cambiásemos el modelo de hosting de asp.net a un modelo cgi en que cada vez que se hace una petición se inicia el w3_wp.exe. Eso por ejemplo lo vemos una barbaridad, pues la gente de google es lo que ha hecho.

No sé si sabéis que en .net existe el mismo problema para los entornos de hosting, un proceso, asp.net o Sql Server. Imaginaros por un momento que tengo mi web en asp.net en un hosting compartido, y una de las web que se aloja en ese servidor, que también está dentro del mismo proceso w3_wp.exe hace una operación no valida y genera una excepción crítica, resulta que el proceso se cerraría y se reiniciaría y yo que también estoy hay sufriría la incompetencia de mi vecino de memoria. Esto desde luego es una cosa muy fuerte, por eso en .NET existe el concepto de Dominio de Aplicación, System.AppDomain, que básicamente es un aislamiento lógico para las aplicaciones, incluso si están dentro del mismo dominio. Esto no es gratuito puesto que a poco que conozcas un poco la plataforma Windows, sabrás que Windows comparte las dll cargas en el mismo proceso, lo que hace que se mejore el consumo de memoria.

Que por cierto si dentro del mismo tab cambias la web el proceso que has usado para renderizar la anterior se cierra y se abre uno nuevo, toda una aberración, ni siquiera reutilizan el proceso, como yo decía un modelo cgi de renderizado de webs. También para los plugins utiliza el mismo proceso, podemos verlo con las líneas de comando.

 

image

Así que lo único que digo sobre el navegador de google, que me importa muy poco, por no decir nada que soporte acid test o lo que sea o los estándares, es que el modelo de aislamiento de tab me parece una castaña muy gorda y que en vez de agitar internet con un lanzamiento de estas características para presentar esta cosa, por favor cállate y presenta algo innovador de verdad.

Actualización: Parece que Microsoft en la beta del IE8 con el UAC activado hace lo mismo, y tengo que decir que me parece una castaña muy gorda, parchear el navegado y no inventar nada nuevo. Yo no tengo el UAC activado.

 

ie8beta22

Windows Vista con UAC gentileza de mi colega Pedro Laguna

 

ie8

Y este es mi escritorio sin UAC con IE8 Beta2 con varios tabs y el process explorer abierto.

Disponible .NET Framework 3.5 SP1 Sources

A través del blog del Reference Source Code Center Team Blog, http://blogs.msdn.com/rscc/archive/2008/08/28/net-framework-3-5-sp1-sources-are-available.aspx, disponible el código fuente del .NET Framework 3.5 SP1. Si trabajáis con el código fuente del framework mientras depuráis las aplicaciones, esta release es justo lo que estabais buscando. Además en el SP1 de Visual Studio 2008 trae directamente el soporte para el código fuente del framework.