Porqué es bueno eliminar la refencia al ensamblado Microsoft.VisualBasic.dll en nuestros proyectos (I)
Introducción
En la última entrada de mi blog, escribí acerca de como eliminar la referencia al ensamblado Microsoft.VisualBasic.dll de nuestros proyectos.
En esa entrada, hubo algunas personas que dieron sus opiniones dentro del apartado de comentarios, algo que agradezco muchísimo, ya que siempre es importante la interactuación de la gente en un blog donde no suele haber un diálogo, sino un intercambio de opiniones o puntos de vista, y los razonamientos y pensamientos se hacen a trompicones.
Las dudas razonables...
Dentro de esos comentarios hubo uno iniciado por delm en el que afirmaba que le daba mucha lástima que se gastara energía en investigar cosas como la que indicaba en mi entrada, y dudaba que esos esfuerzos sirvieran para algo.
Desde luego, que cualquier investigación o análisis sirve, incluso si las conclusiones de esos estudios son nulos. Es positivo que se realicen estudios de todo tipo (con cierto criterio claro está) con el fin de aprender más acerca de las tecnologías y su uso.
Pero no solo es positivo en el campo de la investigación y su uso, sino que a veces es incluso hasta importante u obligatorio.
Por esa razón supongo, delm nos comentaba igualmente que se fundamentara las afirmaciones que se realizan en mi entrada con estudios o profiling en una o varias aplicaciones de un tamaño decente para ver si realmente vale la pena.
A mí me gustaría por otro lado, que delm también realizara esos estudios para fundamentar sus opiniones contrarias. Así nos enriqueceríamos todos.
No obstante, yo ya hice algunos estudios sobre esto hace tiempo, pero ni los tenía a mano, ni sinceramente, me encontraba con ganas de repetirlos debido al poco tiempo libre que tenía para hacer unos estudios concienzudos. Sin embargo, he sacado algo de tiempo para escribir esta segunda entrada y comentar un pequeño y espero que simbólico estudio que he hecho con el fin u objetivo de demostrar el porqué puede ser interesante eliminar al referencia de Microsoft.VisualBasic.dll y usar en su lugar las librerías de .NET.
Lo más sensato es hacer un estudio muchísimo más riguroso, pero espero que este pequeño estudio ofrezca algo de luz a quienes dudan de si es positivo o no eliminar la referencia a Microsoft.VisualBasic.dll.
Recordando...
Recordad, que cuando se llama a un método o función de Microsoft.VisualBasic.dll, ésta se convierte a su método o función equivalente dentro de .NET, lo cuál genera de alguna manera ciertas penalizaciones en el rendimiento de nuestras aplicaciones.
Demostrando...
La pequeña demostración (siento mucho no haber podido hacer una demostración mucho más completa como me hubiera gustado) es la siguiente:
He creado dos clases exactamente iguales en funcionalidad, aunque distintas en cuanto al código escrito, ya que una de ellas se basa en las funciones de VB 6 de Microsoft.VisualBasic.dll y el otro código, se basa en las funciones propias de .NET.
Para estudiar el profiling, me he apoyado en la herramienta JetBrains dotTrace.
Y así, empezamos a codificar la primera clase que he llamado WithReference.
El código de esta primera clase con funciones típicas de VB 6 para .NET es el siguiente:
WithReference.Class1 (Class1.vb):
|
Namespace WithReference
Public Class Class1
Public Function DeleteSpaces(ByVal data As String) As String Return Trim(data) End Function
Public Function TakeLeftRightText(ByVal data As String) As String Return Left(data, 1) & Right(data, 1) End Function
Public Function TransformTextMid(ByVal data As String) As String Dim auxiliarText As String = "" For I As Byte = 1 To Len(data) auxiliarText &= Mid(data, I, 1) Next Return auxiliarText End Function
Public Function TransformTextReplace(ByVal data As String, _
ByVal findCharacter As String, ByVal replaceCharacter As String) As String Return Replace(data, findCharacter, replaceCharacter) End Function
Public Function TransformTextReverse(ByVal data As String) As String Return StrReverse(data) End Function
Public Function TransformTextUpper(ByVal data As String) As String Return UCase(data) End Function
Public Function TransformTextLower(ByVal data As String) As String Return LCase(data) End Function
Public Function GetCharacterPosition(ByVal data As String, ByVal searchText As String) As Byte Return InStr(data, searchText) End Function
Public Sub TestConversion() Dim auxiliarText As String = "" For i As Integer = 0 To 10000 If i Mod 2 = 0 Then ' Convert to String auxiliarText &= Conversion.Int(i).ToString Else ' Convert to Integer (Int32) auxiliarText &= Conversion.Str(i) End If Next End Sub
End Class ' Class1
End Namespace ' WithReference
|
A la segunda clase la he llamado WithoutReference.
El código de la segunda clase con funciones propias de .NET equivalentes a las usadas en la clase anterior es el siguiente:
WithoutReference.Class1 (Class1.vb):
|
Namespace WithoutReference
Public Class Class1
Public Function DeleteSpaces(ByVal data As String) As String Return data.Trim End Function
Public Function TakeLeftRightText(ByVal data As String) As String Return data.Substring(1, 1) & data.Substring(data.Length - 1, 1) End Function
Public Function TransformTextMid(ByVal data As String) As String Dim auxiliarText As String = "" For I As Byte = 0 To data.Length - 1 auxiliarText &= data.Substring(I, 1) Next Return auxiliarText End Function
Public Function TransformTextReplace(ByVal data As String, _
ByVal findCharacter As String, ByVal replaceCharacter As String) As String Return data.Replace(findCharacter, replaceCharacter) End Function
Public Function TransformTextReverse(ByVal data As String) As String Dim charArray(data.Length) As Char For i As Byte = 0 To data.Length - 1 charArray(i) = data(data.Length - (i + 1)) Next Return New String(charArray) End Function
Public Function TransformTextUpper(ByVal data As String) As String Return data.ToUpper End Function
Public Function TransformTextLower(ByVal data As String) As String Return data.ToLower End Function
Public Function GetCharacterPosition(ByVal data As String, ByVal searchText As String) As Byte Return data.IndexOf(searchText, 1) End Function
Public Sub TestConversion() Dim auxiliarText As String = "" For i As Integer = 0 To 10000 If i Mod 2 = 0 Then ' Convert to String auxiliarText &= Convert.ToInt32(i).ToString Else ' Convert to Integer (Int32) auxiliarText &= Convert.ToString(i) End If Next End Sub
End Class ' Class1
End Namespace ' WithoutReference
|
Finalmente he compilado las clases. WithReference con Visual Studio 2008, y WithoutReference siguiendo el patrón de la entrada anterior donde mostraba como compilar una clase con .NET eliminando las referencias a Microsoft.VisualBasic.dll.
La diferencia de tamaños entre las clases son:
- WithReference.dll (11,5 Kb)
- WithoutReference.dll (4,5 Kb)
Además de los tamaños de las clases, existen más diferencias en tiempo de ejecución tal y como veremos a continuación.
Para este experimento, he iniciado una aplicación Windows con C# y con un control Button, al que he agregado una referencia con el ensamblado WithReference.dll.
Dentro del código del formulario windows he escrito el siguiente código:
Aplicación Windows (MainForm.cs):
|
private void btnTestProfiler_Click(object sender, EventArgs e) { this.Text = "Proceso iniciado..."; this.Enabled = false; WithReference.Class1 classTest = new WithReference.Class1(); for (int i = 0; i < 100; i++) { string result; result = classTest.DeleteSpaces(" Testing "); byte position; position = classTest.GetCharacterPosition("Testing", "i"); result = classTest.TakeLeftRightText("Testing"); classTest.TestConversion(); result = classTest.TransformTextLower("ReSuLtS"); result = classTest.TransformTextUpper("ReSuLtS"); result = classTest.TransformTextMid("Text to extract letter by letter"); result = classTest.TransformTextReplace("This is a sample text, to replace it by other different text.", "a", "n"); result = classTest.TransformTextReverse("This is a sample text, to do the reverse of this text."); } this.Text = "Proceso finalizado."; this.Enabled = true; } |
He generado el fichero ejecutable y he copiado el ejecutable y la librería en un directorio aparte.
Una vez hecho esto, he repetido el proceso quitando la referencia a WithReference.dll y agregando una referencia al ensamblado WithoutReference.dll.
El código de la aplicación para este segundo caso es el siguiente:
Aplicación Windows (MainForm.cs):
|
private void btnTestProfiler_Click(object sender, EventArgs e) { this.Text = "Proceso iniciado..."; this.Enabled = false; WithoutReference.Class1 classTest = new WithoutReference.Class1(); for (int i = 0; i < 100; i++) { string result; result = classTest.DeleteSpaces(" Testing "); byte position; position = classTest.GetCharacterPosition("Testing", "i"); result = classTest.TakeLeftRightText("Testing"); classTest.TestConversion(); result = classTest.TransformTextLower("ReSuLtS"); result = classTest.TransformTextUpper("ReSuLtS"); result = classTest.TransformTextMid("Text to extract letter by letter"); result = classTest.TransformTextReplace("This is a sample text, to replace it by other different text.", "a", "n"); result = classTest.TransformTextReverse("This is a sample text, to do the reverse of this text."); } this.Text = "Proceso finalizado."; this.Enabled = true; } |
He vuelto a compilar el proyecto y lo he apartado en otro directorio junto a la librería del ensamblado WithoutReference.dll.
De esta manera, tengo los dos programas listos para ser procesados con la herramienta de rendimiento y profiling.
Estudiando comportamientos...
He arrancado la herramienta JetBrains dotTrace y he ejecutado el primer ejecutable (con el ensamblado WithReference.dll) y he obtenido unos datos muy diferentes a los que muestra el segundo ejecutable (con el ensamblado WithoutReference.dll).
Los datos obtenidos del uso de WithReference.dll los he denominado DatosCon.

Los datos obtenidos del uso de WithoutReference.dll los he denominado DatosSin.

En este punto, lo que tenemos que hacer es estudiar los comportamientos de los dos ensamblados.
En el caso del uso del ensamblado con referencias a Microsoft.VisualBasic.dll, vemos que el proceso de ejecución nos ha durado 24.445 ms, y el proceso principal del control Button, 20.292 ms.
Por su parte, el ensamblado sin referencia a Microsoft.VisualBasic.dll, ha tardado en el proceso general 17.877 ms, mientras que en el proceso principal del control Button, el tiempo que ha tomado es de 15.827 ms.
Algunas conclusiones...
Las conclusiones a simple vista son bastante claras.
El ensamblado que no tiene referencia a Microsoft.VisualBasic.dll, tiene un menor tamaño en su ensamblado y es más rápido en su ejecución.
De todos los modos, tengo pensado agregar alguna entrada más que tendrá por objetivo estudiar algunos de los resultados obtenidos en estas pruebas, y mirar un poco el código intermedio de ambos ensamblados.
Espero que esto, ayude a clarificar aún más mis afirmaciones, las cuales no son verdades absolutas, pero sí pueden ser consideradas por algunos con un poco más de fundamento.
Cross Posted from Jorge Serrano - MVP Visual Developer - VB