Introducción
En mi última entrada, hacía referencia al porqué puede resultar positivo eliminar la referencia al ensamblado Microsoft.VisualBasic.dll en nuestros proyectos de Visual Basic. Lo cierto es que estas cosas no las encuentras en los libros ni te las cuentan prácticamente nadie, porque simplemente, muchas veces no nos cuestionamos algunas cosas. De vez en cuando es bueno preguntarse el porqué y cómo funcionan las cosas, más que dar por hecho una verdad absoluta.
De acuerdo al título de la entrada, en realidad eliminar tal y como pongo en la entrada es quizás una palabra demasiado drástica, pero es lo suficientemente drástica como para llamar la atención, que es lo que precisamente busco, pero quizás lo más razonable sería decir por ejemplo, tratar de evitar el uso de Microsoft.VisualBasic.dll siempre que podamos en lugar de eliminar, pero aún y así, lo más interesante es describir lo nocivo que puede ser resultar el uso de Microsoft.VisualBasic.dll en nuestros proyectos. Cuando llegue a las conclusiones de esta entrada, pregúntese si realmente está más de acuerdo con la palabra eliminar o con la frase evitar el uso, y sobre todo, pregúntese porqué.
No obstante, para sostener la afirmación de mi primera entrada realicé unos primeros y pequeños estudios que ahora trato de completar con un giro de tuerca más sobre el uso de buenas prácticas, las clases, las funciones y los métodos que .NET nos ofrece y que muchas veces obviamos en nuestros desarrollos Software.
Recordando los resultados del estudio anterior...
Para esta entrada, me baso en el estudio diferencial existente entre el ensamblado que usa Microsoft.VisualBasic.dll y el ensamblado al que hemos eliminado el uso de esta librería que vimos en la entrada anterior.
Adicionalmente, me apoyo en otro estudio y buenas prácticas que realicé en una entrada de Diciembre de 2006 y que podeis encontrar aquí esta entrada. En esa entrada, argumentaba un estudio sobre la iteración de cadenas en nuestras aplicaciones .NET. Argumentos y estudios que me sirven ahora para argumentar más aún algunas tesis que según mi modesto punto de vista, no son nada despreciables y que muestran las bondades de .NET vs el uso de instrucciones de Visual Basic 6 utilizadas en .NET.
Para tratar de ser justos, he vuelto a repetir las pruebas con JetBrains dotTrace que hice en la entrada anterior y he obtenido los siguientes datos:
La hebra de la aplicación (DatosCon) que utiliza el ensamblado que posee referencias a Microsoft.VisualBasic.dll tarda en total 21.722 ms, y en el proceso del control Button, 20.037 ms.
La hebra de la aplicación (DatosSin) que utiliza el ensamblado que no posee referencias a Microsoft.VisualBasic.dll tarda en total 17.692 ms, y en el proceso del control Button, 15.561 ms.
Es decir, la diferencia entre la hebra del primer (DatosCon) y segundo proceso (DatosSin) es de 4.030 ms. 4 segundos son muchos segundos.
Estudiando un poco más a fondo todos estos resultados, lo verdaderamente importante no es la comparación de la ejecución de la hebra completa, ya que el proceso entero está basado en hacer el clic manualmente sobre el control Button, y es posible que esa diferencia de milisegundos esté motivada por mi reacción y pulso más que otra cosa.
Así que donde me quiero parar realmente es en el estudio de la hebra del control Button, que es la que realmente me intesa.
Ahí, la diferencia entre ambos procesos es de 4.476 ms a favor de (DatosSin), es decir, el proceso de ejecución que utiliza el ensamblado que no tiene referencia a Microsoft.VisualBasic.dll es casi 4 segundos y medio más rápido que el mismo proceso de (DatosCon). Si miramos las pruebas que hice de la entrada anterior, la diferencia entre ambos procesos es de 4.465 ms, así que ms arriba ms abajo, estamos más o menos dentro de esos márgenes.
Girando la tuerca un poco más...
Pero claro... aquí no acaba esto, ya que lo más sensato es comparar los dos ensamblados.
Me parece estupendo que uno de ellos "gane", pero ¿estamos seguros de que el ensamblado "ganador" es un ensamblado "perfecto"?.
Yo siempre digo que no hay nada perfecto, y cuando se habla de tecnología muchísimo menos. De hecho, lo voy a demostrar.
Utilizando nuevamente la herramienta JetBrains dotTrace, soy capaz de comparar ambos estudios y ver donde están los "cuellos de botella" o esas diferencias más notables.
En la siguiente imagen, podemos ver esas diferencias de forma gráfica:

Si atendemos a esta información, podremos observar que hay diferentes partes que están en color rojo.
Examinando todas las partes, nos damos cuenta de que hay una parte de la información que nos resulta llamativa. Me refiero a la parte del método TestConversion.

Según ese método, en el caso del uso de la librería WithoutReference.dll, el método que se ejecuta dentro del clic del control Button, consume la friolera cantidad de 15.539 ms de los 15.561 ms que consume todo el código contenido en el control Button.
Para estar utilizando funciones de .NET, el resultado no es que digamos esperanzador, por lo que lo primero que debemos hacer es estudiar el código de ese método.
Estudiando el código y aportando soluciones...
El método TestConversion tiene la funcionalidad de concatenar cadenas.
Concatenar cadenas es mucho más costoso que utilizar por ejemplo la clase StringBuilder que encontraremos en el nombre de espacio System.Text.
De acuerdo a la entrada que escribí en Diciembre del 2006 en el que mostraba la forma eficiente de trabajar con cadenas, deberíamos modificar el código de nuestra aplicación, para mejorar aún más el rendimiento del ensamblado que no utiliza Microsoft.VisualBasic.dll. El objetivo: crear un ensamblado lo más eficiente posible.
De esta forma, el código de nuestro ejemplo de acuerdo al método TestConversion, quedaría de la siguiente forma:
WithoutReference.Class1 (Class1.vb):
|
...
Public Sub TestConversion() Dim auxiliarText As New System.Text.StringBuilder For i As Integer = 0 To 10000 If i Mod 2 = 0 Then ' Convert to String auxiliarText.Append(Convert.ToInt32(i).ToString) Else ' Convert to Integer (Int32) auxiliarText.Append(Convert.ToString(i)) End If Next End Sub ... |
Si prestamos atención al código anterior, veremos que lo que hacemos es apoyarnos en la clase StringBuilder para realizar el mismo proceso.
En este punto, podría preguntarse si podríamos utilizar StringBuilder en el ensamblado que hace referencia a Microsoft.VisualBasic.dll. La respuesta es sí, por supuesto, pero si va a utilizar este objeto propio de .NET, ¿porqué no utiliza desde el principio solo y únicamente los objetos propios de .NET?. Se ahorraría problemas seguramente.
De hecho, el "cuello de botella" del ensamblado que hace uso de Microsoft.VisualBasic.dll está localizado dentro del mismo método, por lo que si utilizáramos StringBuilder, es prácticamente seguro que obtendríamos unos resultados muy óptimos, pero le aseguro, que los resultados más óptimos se encuentran localizados en el ensamblado que no hace uso de Microsoft.VisualBasic.dll. De todos los modos, aquí lo que tratamos de comparar son las funciones y métodos propios de Microsoft.VisualBasic.dll vs las funciones y métodos propios de .NET.
Si una vez modificado el código anterior ejecutamos nuestra aplicación, obtendremos unos resultados sorprendentes.
Estudiando los resultados...
De acuerdo a los nuevos resultados obtenidos, estos arrojan unos datos demoledores a favor de las instrucciones de .NET.
En la siguiente imagen podemos ver la tabla de resultados:

Ahora y gracias a StringBuilder, podemos indicar que la ejecución total de la hebra es de 1.932 ms, mientras que la ejecución del control Button que contiene todas las instrucciones que nos importan, es de 795,4 ms. Ni siquiera 1 segundo. Dentro de esta parte, seguimos observando que TestConversion sigue consumiendo gran parte del tiempo de proceso de ejecución, pero hemos pasado de 15.539 ms a 772,6 ms.
La diferencia es notable evidentemente.
Sobre ILDASM...
Utilizando la herramienta ILDASM que viene con .NET Framework y que permite estudiar el código intermedio de nuestras aplicaciones, podemos apreciar que las diferencias reales entre los dos ensamblados (el ensamblado que tiene la referencia a Microsoft.VisualBasic.dll y el ensamblado que no tiene referencia a ese ensamblado) son mínimas.
Si se estudia con detenimiento el código intermedio, se pueden ver algunos pequeños detalles en el ensamblado con referencia a Microsoft.VisualBasic.dll que no tiene el otro ensamblado, como algún ajuste de conversión.
De todos los modos, lo mejor es utilizar .NET Reflector y mirar las clases, métodos y funciones de Microsoft.VisualBasic.dll, y comprobar como funciona realmente "por debajo".
Algunas conclusiones...
-
Ante esto tenemos una opción muy clara y evidente con una afirmación mucho más drástica si cabe: el uso exclusivo de Microsoft.VisualBasic.dll no nos favorece. Es decir, si lo que queremos es utilizar únicamente instrucciones de Microsoft.VisualBasic.dll, es prácticamente seguro que penalizaremos en rendimiento a nuestra aplicación. ¿Cuál es la penalización?. En realidad depende de cada proyecto, del código escrito en él, sus iteraciones, etc.
-
El uso híbrido de Microsoft.VisualBasic.dll e instrucciones puras .NET puede resultarnos útil y ventajoso. No es quizás lo más ventajoso, pero es claramente más favorable que el uso único y exclusivo de instrucciones heredadas de Visual Basic 6.
-
Si decidimos por un híbrido entre instrucciones puras .NET e instrucciones extraídas el ensamblado Microsoft.VisualBasic.dll, ¿porqué no utilizar directamente y únicamente las instrucciones de .NET?. Ese sería el escenario más adecuado y positivo. Por esa razón, una forma de habituarnos a trabajar sin el ensamblado Microsoft.VisualBasic.dll en Visual Studio 2008, es acceder a las Propiedades del proyecto y abrir la solapa de Referencias. Dentro de esa solapa, quitar la selección o la referencia al ensamblado Microsoft.VisualBasic.dll. De esta manera, el entorno nos avisará con un mensaje de error si estamos utilizando alguna instrucción de Visual Basic 6 habilitada por medio de Microsoft.VisualBasic.dll.
Así, ¿cuantas veces utiliza (yo lo hago) la instrucción VbCrLf?. Pues quizás no lo sepa, pero VbCrLf pertenece a la clase Contants del nombre de espacio Microsoft.VisualBasic. ¿Sorprendido?. Quizás lo lógico es utilizar \r\n en C#, o Environment.NewLine() en .NET, ¿pero VbCrLf?.
Como podemos ver, los "vicios" adquiridos y arrastrados por los desarrolladores que venimos de Visual Basic 6.0 son muchos, y erradicarlos va a ser un proceso muy largo y tedioso. ¿Porqué no empezar desde ya?.
Cross Posted from Jorge Serrano - MVP Visual Developer - VB