[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.

[Curso] WPF para programadores de Windows Forms 6

En la última entrega del curso de WPF para programadores de Windows Forms, hablamos de los DataTemplate, que permitían modificar el aspecto visual de un control. Ahora en este articulo vamos a hablar un poco más sobre esta característica y como se puede extender.

Imaginemos por un momento que empezamos a usar esta característica que junto con los estilos permiten modificar el aspecto de un control de una manera muy sencilla, pero que ahora queremos que el usuario, por ejemplo, elija un tema de una lista de temas disponibles. ¿Cómo podríamos encajar esta funcionalidad con los DataTemplate tendríamos que tener algún mecanismo para poder decidir en tiempo de ejecución que DataTemplate tenemos que elegir. Pero la pregunta es cuando hacemos esto ¿cuando el control se ha cargado?, ¿en el constructor?, la respuesta es DataTemplateSelector .

Esta clase, DataTemplateSelector provee una manera de elegir un DataTemplate en tiempo de ejecución, cuando el control se va a enlazar y se va a construir el árbol visual de controles de nuestro elemento.

DataTemplateSelector tiene un método virtual,

public virtual DataTemplate SelectTemplate(Object item, DependencyObject container)

En el que se nos pasa la referencia del objeto de datos el cual el control está enlazado y el control en sí que es pasado en el container. De esta manera y a través de un enlace a datos podemos decidir que DataTemplate tenemos que establecer. Una vez que tenemos una clase que hereda de DataTemplateSelector, y hemos sobreescrito el método SelectTemplate, tenemos que crear una instancia de esta clase y establecerlo en la propiedad ContentTemplateSelector de la clase ContentControl.

Sería algo parecido a esto:

using System.Windows;
using System.Windows.Controls;

namespace SDKSample
{
    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate

                SelectTemplate(object item, DependencyObject container)
        {
            if (item != null && item is Task)
            {
                Task taskitem = item as Task;
                Window window = Application.Current.MainWindow;
                if (taskitem.Priority == 1)
                    return
                    window.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                    window.FindResource("myTaskTemplate") as DataTemplate;
            }
            return null;
        }
    }
}

Otra necesidad que se nos puede surgir es de generar DataTemplates a partir de código, esto que a priori no es recomendable puesto que añade complejidad extra al código y no permite modificar el aspecto del control a través del xaml y puede que en algún momento sea necesario además de que es necesario recompilar la aplicación.

Si echamos un vistazo a la clase DataTemplate vemos que tiene una propiedad VisualTree, que es el nodo raíz del DataTemplate, el control raíz del DataTemplate. Pero si nos paramos a ver por un momento el tipo de esta propiedad vemos que es de tipo FrameworkElementFactory y no DependencyObjecto Control como podríamos esperar. Esta clase FrameworkElementFactory es en realidad una factoría de FrameworkElement, y es usada por el constructor de controles para inicializar un control. Si nos fijamos en el construcor de esta clase el parámetro que se nos pide es un System.Type que después usara para crear un objeto de ese tipo con System.Activator.

Si miramos los métodos de que dispone esta clase tenemos:

· AddHandler, que nos permite añadir un manejador a un RouteEvent.

· AppendChild, que permite añadir un hijo al elemento actual.

· RemoveHandler, que permite eliminar un manejador previamente creado.

· SetBinding, que permite añadir un binding.

· SetValue, esta es si cabe es el método más interesante de todos ya que nos permite establecer valores de los DP de nuestro control.

En una inicialización normal de un control de WPF podríamos hacer algo así:

Grid grid = new Grid();

Grid.Margin = new Thinkness(3);

Realmente la propiedad Margien es un wrapper en una propiedad del CLR de un DependencyProperty llamado MarginProperty.

Esta sería la manera de hacerla con WPF:

Grid grid = new Grid();

Grid.SetValue(Grid.MarginProperty,new Thinkness(3));

Así que la clase FrameworkElementFactory guarda una lista de los DP que se han establecido para después establecerlos en el control que instancia internamente.

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.