Memory leaks en JavaScript

Despues de mucho tiempo desarrollando en C++, los memory leaks es algo que no me asustaba, aunque evidentemente una de las cosas que me encantaban de .Net era el no tener que consumir mi tiempo en largas sesiones de depuración y relectura de código buscando fugas de memoria.


Pero la vida es dura, y aunque ahora principalmente esté desarrollando aplicaciones web con Asp.net, los memory leaks están de vuelta. Y es que la Web 2.0 esta aquí, con millones de lineas de JavaScript en la mochila, y o sorpresa Internet Explorer puede fugar memoria cuando usas JavaScript de maneras que son perfectamente legales. Así que de nuevo me veo buscando memory leaks.


Si vuestra aplicación tienen código JavaScript, no os perdaís este articulo: Understanding and Solving Internet Explorer Leak Patterns


Además como en el caso de C++, si ya hemos cometido errores,hay algunas herramientas que nos puede ayudar:


IEMemoryLeaks


JavaScript Lint

Arquitectos y modistas

Mi abuela a cosido todo su vida. La recuerdo con sus gafas, su cesto de costura y sus patrones. Nunca la vi cortar una falda o un abrigo sin utilizar patrones. El otro dia la pregunte: Abuela, ¿Por qué siempre utilizas patrones? Llevas siglos cosiendo y sin embargo nunca cortas una falda sin usarlos (tarea realivamente facil para una modista experimentada). La respuesta, con una mirada de incredulidad y desconfianza (como si la tomase el pelo), fue clara: ¿Estas loco? Y que pasa si me equivoco y tengo que tirar todo el paño de tela, hasta el mejor escribano hecha un borrón!. Además tengo que hacer diferentes tallas.

Sin duda mi abuela es una mujer lista, ha descubierto lo mismo que yo, los patrones protegen de los errores, y los errores cuestan tela (o dinero, otra de sus acepciones, no creo que sea casualidad…). Solo que ella lo aplica a la costura, yo lo aplico al diseño y la arquitectura del software. Este sin duda es para mi el principal valor de los patrones, si haces algo siguiendo un patrón es mucho más probable que no te equivoques, hasta mi abuela lo tiene claro. El otro valor son las 'diferentes tallas', y es que un patrón se aplica en muchos contextos aportando, por lo tanto, una metasolución universal que nos ayuda a encontrar una buena solución en nuestro contexto particular.

Aprovecho para comentaros que mi amiguete Gorka Elexgaray, compañero mio en durante mi tiempo en Panda Software y ahora en Sisteplant (una pena que no lo sea tambien en [PC], pero es un tipo ocupado que le vamos a hacer…) me ha mandado un intersante link, que habla sobre el proyecto ET++. De por si no es especialmente interesante, otro de los mil frameworks que existen para interfaz de usuario en C++. No se si bueno o malo nunca lo he usado. Pero intuyo que malo del todo no será puesto que usa patrones intensivamente. El interés que tiene es que la gente que ha diseñado este framework se ha preocupado de documentar donde y por que a utilizado cada patrón que ha empleado. Hechadle un vistazo al link: http://research.microsoft.com/~minka/patterns/ET++/

Y si quereis saber más sobre patrónes (y otro montón de temas): [CMVP]

Buenas noticias para los madrugadores del unit testing…

Andaba buscando una herramienta para convertir mis ‘viejos’ test de NUnit en test de Visual Studio 2005, y es que depués de unos 2 años usandolos tengo unos cuantos en mis proyectos y la verdad los he cojido cariño…


Pues bueno, lo importante es que he encontrado esta herramienta, como no podía ser de otra forma a sido en Gotdotnet, que esta lleno de tesoros…


Para aquellos interesados en esta herramienta llamada NUnit Converter (de qué otro modo se podía llamar) aquí va el link: NUnit Converter

SQL Server 2005 Report Packs ya disponibles

La semana pasada salieron los SQL Server 2005 Report Packs, que son informes y bases de datos de ejemplo para diferentes aplicaciones y tecnologias de Microsoft.


Los diferentes packs son:


SQL Server 2005 Report Pack for SQL Server Integration Services
SQL Server 2005 Report Pack for Microsoft SharePoint Portal Server 2003
SQL Server 2005 Report Pack for Microsoft Dynamics Axapta 3.0
SQL Server 2005 Report Pack for Microsoft Dynamics Navision 4.0
SQL Server 2005 Report Pack for Microsoft Dynamics Great Plains 8.0
SQL Server 2005 Report Pack for Microsoft Dynamics Great Plains 9.0
SQL Server 2005 Report Pack for Microsoft Internet Information Services (IIS)
SQL Server 2005 Report Pack for Financial Reporting


Podeis descargarlos desde:


http://www.microsoft.com/downloads/details.aspx?familyid=d81722ce-408c-4fb6-a429-2a7ecd62f674&displaylang=en


Seguro que os serán de utilidad.

Activar una instancia anterior de una aplicación MFC basada en dialogos

Básicamente se trata de buscar la ventana con FindWindow y luego ponerla en primer plano llamando a SetForegroundWindow


Aqui va un poco de código…


BOOL COnlyOneApp::InitInstance()
{
   //#32770 es la clase de ventana que usan los cuadros de dialogo  MFC
   //OnlyOne es el titulo de la ventana
   HWND hwnd = ::FindWindow(“#32770”, “OnlyOne”);
   if (hwnd != NULL)
   {
      SetForegroundWindow(hwnd);
   return FALSE; //Devolvemos FALSE para que acabe la ejecución.
   }
   //Resto de la función Instance…..
   .
   .
}

Lo habitual es registrar tu propia clase de ventana con nombre unico, y pasar NULL como segundo parametro a la función FindWindow.

Para saber como registrar tu propia clase de ventana en una aplicación basada en dialogos:
http://support.microsoft.com/kb/251059

Para ver un ejemplo de todo esto, existe un ejemplo que se llama ONETIME, en los ejemplo de Visual Studio.

Jugando con System.Transactions

Sin duda la capacidad de usar ámbitos de transacción es un gran avance en lo que a legibilidad, mantenibilidad y claridad de interfaces se refiere. Se termina la necesidad de ir pasando objetos que representen una transacción de un método a otro para que las operaciones de datos puedan realizar en la misma transacción.

Si bien no es una novedad radical, puesto que el mismo efecto se podía lograr usando el namespace System.EnterpriseServices y derivando nuestra clase de ServicedComponent, el hecho de que ya no sea necesario derivar de ServicedComponent hacer que nuestras jerarquías de clases sean mucho más naturales.

Además las transacciones de System.EnterpriseServices siempre están controladas por el DTC (Distributed Transactions Coordinator), lo que añade más coste de ejecución a estas. Usando System.Transactions, sin embargo, las transacciones solo se promocionan a transacciones del DTC (transacciones distribuidas) cuando es necesario, y en principio, eso solo es necesario si estamos tratando con diferentes fuentes de datos.

Hasta aquí las buenas noticias. La mala noticia es que si utilizamos diferentes conexiones para realizar operaciones de datos, aunque sean a la misma fuente de datos, y con la misma cadena de conexión, las transacción se promociona al DTC. Esto nos deja en la misma situación que queríamos evitar, puesto que si queremos evitar esto debemos pasar la conexión como parámetro de nuestros métodos.

Cuando David Carmona y Unai Zorrilla, en su visita a Bilbao para la gira de presentación de VS 2005, en la que los tres participábamos, me comentaban esta situación no me lo podía creer. Luego pensé, vale, se escala al DTC y eso no es bueno, sin duda, pero como de malo es, ¿cual es el coste de escalar al DTC y como afecta al rendimiento de la aplicación?

Y dispuesto a contestar esta pregunta, he abierto el VS esta mañana. Y puedo adelantar que no me gusta lo que he descubierto. Sin bien también he de reconocer que el entorno utilizado para las pruebas no es la mejor, un portátil mono procesador, corriendo Sql Server, el DTS y las pruebas. En cuanto pueda las repetiré en un servidor.

Me he hecho un programita en C# que podéis descargar DTCTest Source Code, que básicamente lo que hacer es una serie de inserciones en una tabla en una transacción, una vez usando la misma conexión, otras usando dos conexiones diferentes, lo que hacer que la transacción se promocione al DTC. El programa hace esto de 1000 a 10000 veces en intervalos de 1000 y muestra el tiempo que tardó la operación. 

El primero problema que he encontrado ha sido ¿Cómo saber cuando las transacciones están promocionándose al DTC? He encontrado dos soluciones, mediante programación, utilizando el evento DistributedTransactionStarted de la clase TransactionManager. Evidentemente esto no me sirve del todo para mis pruebas, puesto que controlar este evento, como es evidente y la propia documentación advierte penaliza el rendimiento de las transacciones.

El segundo método es simple, menú Inicio->Herramientas administrativas->Servicios de Componentes. En el árbol que aparece, Sevicios de Componentes->Mi PC->Coordinador de Transacciones->Estadísticas de Transacciones. Esta pantalla muestra la cantidad de transacción distribuidas en progreso.

El segundo problema es algo curioso:

¿Qué pensaría cualquier programador de un código como este?


cn2.Open();
cn3.Open();

using (TransactionScope t = new TransactionScope(TransactionScopeOption.RequiresNew, tso))
{
   
cm.Connection = cn2;
   
cm.ExecuteNonQuery();
   
cn2.Close();
   
   
cm.Connection = cn3;
   
cm.ExecuteNonQuery();
   
cn3.Close();
}
 

Lógicamente como no se llama a t.Completed() antes de salir del ámbito de la transacción la misma no debería completarse, pero lo que en realidad ocurre es que los cambios si se realizan en la base de datos. Este código en apariencia hace un cosa y en la realidad otra. El motivo es que lo que marca que la operación de base de datos este dentro o no del ámbito de transacción es cuando se llama al método Open de la conexión que se utiliza para realizar la operación de base de datos. Esto es propenso a errores, porque lo que todo programador tiende a pensar es que es suficiente que la ejecución del comando esté dentro del ámbito de la transacción.

Con los resultados de mi prueba he construido el siguiente gráfico:

Este gráfico deja claro que, sin el DTC de por medio, el tiempo de ejecutar las transacciones crece linealmente. Lo problemático es que cuando el DTC entra en juego. Este tiempo se va incrementando exponencialmente y esta es una pésima noticia, porque significa que a más transacciones, más coste por transacción, lo cual es extremadamente negativo para la escalabilidad de nuestras aplicaciones. No me puedo creer estos resultados, por lo tanto estoy revisando el procedimiento de prueba que he realizado y no considero nada definitivo hasta que no corra estas pruebas en un entorno más adecuado. Ya os contaré…

ACTUALIZACIÓN: Debes leer Sobre las transacciones, las conexiones, el LTM y el DTC de Iván González!!! Desentraña el misterio de la escalabilidad exponecial.