<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Entre Códigos &#187; laboratorio</title>
	<atom:link href="http://www.entrecodigos.com/temas/laboratorio/feed" rel="self" type="application/rss+xml" />
	<link>http://www.entrecodigos.com</link>
	<description>Reflexiones de un cerebro en fuga y artículos sobre posicionamiento, e-marketing, usabilidad y otros tecnicismos.</description>
	<lastBuildDate>Sun, 30 May 2010 10:46:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Probando el rendimiento de LINQ en ASP.Net</title>
		<link>http://www.entrecodigos.com/2009/07/probando-el-rendimiento-de-linq-en-aspnet.html</link>
		<comments>http://www.entrecodigos.com/2009/07/probando-el-rendimiento-de-linq-en-aspnet.html#comments</comments>
		<pubDate>Fri, 03 Jul 2009 07:00:44 +0000</pubDate>
		<dc:creator>Ruben Cantón</dc:creator>
				<category><![CDATA[laboratorio]]></category>
		<category><![CDATA[taller]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[linq]]></category>

		<guid isPermaLink="false">http://www.entrecodigos.com/?p=1096</guid>
		<description><![CDATA[
Después de haber aprendido lo que es LINQ y cómo funciona, es obligado ver si, además de simplificar el código, mejora la eficiencia de nuestro proyecto.
Me he decidido por probar la lectura de archivos XML por parte de LINQ y determinar quien tiene mayor velocidad de lectura, la librería de acceso a XML de .Net [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://img5.imageshack.us/img5/6633/linqbanner.jpg" class="aligncenter" alt="LINQ" /><br />
Después de haber aprendido lo <a href="http://www.entrecodigos.com/2009/05/iniciacion-a-linq-en-aspnet.html">que es LINQ y cómo funciona</a>, es obligado ver si, además de simplificar el código, mejora la eficiencia de nuestro proyecto.</p>
<p>Me he decidido por <strong>probar la lectura de archivos XML por parte de LINQ</strong> y determinar quien tiene mayor velocidad de lectura, la librería de acceso a XML de .Net o la nueva tecnología: LINQ. Para ello, <strong>he creado un XML con 100.000 registros</strong> que simula una tabla de alumnos y realizaré consultas a dicho XML.</p>
<p>Éstas son las consultas que he decidido realizar utilizando ambos sistemas:</p>
<ul>
<li><strong>Prueba 1</strong>: Extraer todos los alumnos que se llamen Jorge.</li>
<li><strong>Prueba 2</strong>: Contar cuantos alumnos han aprobado.</li>
<li><strong>Prueba 3</strong>: De entre los alumnos que se llaman Jorge, ¿cuántos han suspendido?</li>
<li><strong>Prueba 4</strong>: De entre los alumnos que han sacado más de un 8, ¿cual es el nombre más predominante?</li>
<li><strong>Prueba 5</strong>: Extraer sólo los nombres distintos de los alumnos y ordenarlos..</li>
</ul>
<p><span id="more-1096"></span>Y tras lanzar las mismas aquí están, en segundos, los tiempos que ha tardado cada método en cada una de las consultas anteriores:</p>
<table border="1" bordercolor="grey" cellpadding="4" cellspacing="0" style="margin:0 auto;">
<tr style="text-align:center;">
<td>Prueba</td>
<td>XML Reader</td>
<td>LINQ</td>
</tr>
<tr>
<td>1</td>
<td>0,301934</td>
<td>0,000036</td>
</tr>
<tr>
<td>2</td>
<td>0,589991</td>
<td>0,090168</td>
</tr>
<tr>
<td>3</td>
<td>0,390582</td>
<td>0,054944</td>
</tr>
<tr>
<td>4</td>
<td>0,432305</td>
<td>0,091441</td>
</tr>
<tr>
<td>5</td>
<td>0,281885</td>
<td>0,042886</td>
</tr>
</table>
<p>Se puede apreciar claramente la diferencia en velocidades de acceso, siendo el <strong>XML Reader entre 7 y 8 veces más lento que LINQ</strong>. Pero además, las consultas en LINQ me han ocupado entre 1 y 3 líneas (y porque he querido dividirlo en líneas) mientras que las realizadas con el antiguo método ocupaban entre 10 y 30 líneas.</p>
<p>Por todo esto, LINQ parece batir al XML Reader tanto en velocidad de acceso como en simplificación de código, lo que <strong>reduce errores y costes de producción o mantenimiento</strong>.</p>
<p>Sé que <strong>existen otros métodos para acceder a un XML</strong> en .Net (la librería de XML ofrece otras opciones), pero yo me he decantado por ésta, quizás alguna otra resultase más eficiente, pero tras realizar varias pruebas con LINQ, realmente me ha convencido como tecnología de acceso a conjuntos de datos.</p>
<p>Por último, dejo aquí el código fuente utilizado, por si a alguien le pica la curiosidad o he metido la pata y alguien puede corregirme:</p>
<pre>
    Private Sub TestVelocidad1()
Dim rutaArchivo As String = "C:/test/xmlAlumnos100.xml"
Dim metodoReader As System.Xml.XmlTextReader
Dim metodoLINQ As System.Xml.Linq.XDocument = System.Xml.Linq.XDocument.Load(rutaArchivo)
Dim lstAlumnos As New Collections.Generic.List(Of Alumno)
Dim lstNombres As New Collections.Generic.List(Of String)
Dim oAlumno As Alumno = Nothing
Dim notaAux As Byte = 0
Dim cantAprobados As Integer = 0
Dim cantSuspendidos As Integer = 0

Page.Trace.IsEnabled = True

'Prueba 1: Extraer todos los alumnos que se llamen Jorge.
Trace.Warn("Empieza la prueba 1")
Dim alumnos = From alum In metodoLINQ.Descendants("alumno") _
Where alum.Attribute("nombre") IsNot Nothing AndAlso alum.Attribute("nombre").Value = "Jorge" _
Select Nombre = alum.Attribute("nombre").Value, Nota = alum.Attribute("nota").Value
Trace.Warn("Fin prueba 1 con LINQ")

metodoReader = New System.Xml.XmlTextReader(rutaArchivo)
Do While metodoReader.Read
If metodoReader.NodeType = System.Xml.XmlNodeType.Element AndAlso metodoReader.Name = "alumno" AndAlso metodoReader.HasAttributes Then
oAlumno = New Alumno
While metodoReader.MoveToNextAttribute
If metodoReader.Name = "nombre" Then
oAlumno.Nombre = metodoReader.Value
If oAlumno.Nombre &lt;> "Jorge" Then Exit While
ElseIf metodoReader.Name = "nota" Then
Byte.TryParse(metodoReader.Value, oAlumno.Nota)
End If
End While
If oAlumno.Nombre = "Jorge" Then lstAlumnos.Add(oAlumno)
End If
Loop
Trace.Warn("Fin prueba 1 con Reader")

'Prueba 2: Contar cuantos alumnos han aprobado.
Trace.Warn("Empieza la prueba 2")
cantAprobados = (From alum In metodoLINQ.Descendants("alumno") Where alum.Attribute("nota") IsNot Nothing AndAlso Integer.Parse(alum.Attribute("nota").Value) > 4).Count
Trace.Warn("Fin prueba 2 con LINQ")

metodoReader = New System.Xml.XmlTextReader(rutaArchivo)
cantAprobados = 0
Do While metodoReader.Read
If metodoReader.NodeType = System.Xml.XmlNodeType.Element AndAlso metodoReader.Name = "alumno" AndAlso metodoReader.HasAttributes Then
notaAux = 0
While metodoReader.MoveToNextAttribute
If metodoReader.Name = "nota" Then
Byte.TryParse(metodoReader.Value, notaAux)
If notaAux > 4 Then cantAprobados += 1
End If
End While
End If
Loop
Trace.Warn("Fin prueba 2 con Reader")

'Prueba 3: De entre los alumnos que se llaman Jorge, ¿cuántos han suspendido?
Trace.Warn("Empieza la prueba 3")
cantSuspendidos = (From alum In metodoLINQ.Descendants("alumno") _
Where alum.Attribute("nombre") IsNot Nothing AndAlso alum.Attribute("nombre").Value = "Jorge" _
Where alum.Attribute("nota") IsNot Nothing AndAlso Integer.Parse(alum.Attribute("nota").Value) &lt; 5).Count
        Trace.Warn("Fin prueba 3 con LINQ")

        metodoReader = New System.Xml.XmlTextReader(rutaArchivo)
        cantSuspendidos = 0
        oAlumno = New Alumno
        Do While metodoReader.Read
            If metodoReader.NodeType = System.Xml.XmlNodeType.Element AndAlso metodoReader.Name = "alumno" AndAlso metodoReader.HasAttributes Then
                notaAux = 0 : oAlumno.Nombre = "" : oAlumno.Nota = 0
                While metodoReader.MoveToNextAttribute
                    If metodoReader.Name = "nota" Then Byte.TryParse(metodoReader.Value, oAlumno.Nota)
                    If metodoReader.Name = "nombre" Then oAlumno.Nombre = metodoReader.Value
                End While
                If oAlumno.Nombre = "Jorge" And oAlumno.Nota &lt; 5 Then cantSuspendidos += 1
            End If
        Loop
        Trace.Warn("Fin prueba 3 con Reader")

        'Prueba 4: De entre los alumnos que han sacado más de un 8, ¿cual es el nombre más predominante?
        Dim NombreMasEmpollon As String = ""
        Trace.Warn("Empieza la prueba 4")

        Dim empollon As Generic.List(Of String) = (From n In (From alum In metodoLINQ.Descendants("alumno") _
            Where (alum.Attribute("nota") IsNot Nothing AndAlso Integer.Parse(alum.Attribute("nota").Value) > <img src='http://www.entrecodigos.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> _
            Group alum By nombre = alum.Attribute("nombre").Value Into cantNombres = Count() _
            Select nombre, cantNombres Order By cantNombres Descending Order By cantNombres Descending Take 1) Select n.nombre).ToList
        NombreMasEmpollon = empollon.Item(0).ToString
        Trace.Warn("Fin prueba 4 con LINQ")

        metodoReader = New System.Xml.XmlTextReader(rutaArchivo)
        Dim klstNombres As New Generic.SortedList(Of String, Integer)
        oAlumno = New Alumno
        Do While metodoReader.Read
            If metodoReader.NodeType = System.Xml.XmlNodeType.Element AndAlso metodoReader.Name = "alumno" AndAlso metodoReader.HasAttributes Then
                oAlumno.Nombre = "" : oAlumno.Nota = 0
                While metodoReader.MoveToNextAttribute
                    If metodoReader.Name = "nota" Then Byte.TryParse(metodoReader.Value, oAlumno.Nota)
                    If metodoReader.Name = "nombre" Then oAlumno.Nombre = metodoReader.Value

                    If oAlumno.Nota > 0 And oAlumno.Nombre.Length > 0 Then
                        If oAlumno.Nota > 8 Then
                            If klstNombres.Keys.IndexOf(oAlumno.Nombre) &lt; 0 Then
                                klstNombres.Add(oAlumno.Nombre, 1)
                            Else
                                klstNombres.Item(oAlumno.Nombre) = klstNombres.Item(oAlumno.Nombre) + 1
                            End If
                        End If
                        Exit While
                    End If
                End While
            End If
        Loop
        NombreMasEmpollon = klstNombres.Keys(0)
        For Each n As String In klstNombres.Keys
            If klstNombres(n) > klstNombres(NombreMasEmpollon) Then
                NombreMasEmpollon = n
            End If
        Next
        Trace.Warn("Fin prueba 4 con Reader")

        'Prueba 5: Extraer sólo los nombres distintos de los alumnos y ordenarlos.
        Trace.Warn("Empieza la prueba 5")
        Dim nombres As String() = (From alum In metodoLINQ.Descendants("alumno") Select n = alum.Attribute("nombre").Value Distinct Order By n.ToString).ToArray
        Trace.Warn("Fin prueba 5 con LINQ")

        metodoReader = New System.Xml.XmlTextReader(rutaArchivo)
        lstNombres.Clear()
        Do While metodoReader.Read
            If metodoReader.NodeType = System.Xml.XmlNodeType.Element AndAlso metodoReader.Name = "alumno" AndAlso metodoReader.HasAttributes Then
                While metodoReader.MoveToNextAttribute
                    If metodoReader.Name = "nombre" Then
                        If lstNombres.IndexOf(metodoReader.Value) &lt; 0 Then
                            lstNombres.Add(metodoReader.Value)
                        End If
                        Exit While
                    End If
                End While
            End If
        Loop
        lstNombres.Sort()
        Trace.Warn("Fin prueba 5 con Reader")

    End Sub

Public Class Alumno

#Region "Variables"
    Private _nombre As String
    Private _nota As Byte
#End Region

#Region "Propiedades"
    Public Property Nombre() As String
        Get
            Return _nombre
        End Get
        Set(ByVal value As String)
            _nombre = value
        End Set
    End Property
    Public Property Nota() As Byte
        Get
            Return _nota
        End Get
        Set(ByVal value As Byte)
            _nota = value
        End Set
    End Property
#End Region

End Class
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.entrecodigos.com/2009/07/probando-el-rendimiento-de-linq-en-aspnet.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Probando Bing, el nuevo buscador de Microsoft</title>
		<link>http://www.entrecodigos.com/2009/06/probando-bing-el-nuevo-buscador-de-microsoft.html</link>
		<comments>http://www.entrecodigos.com/2009/06/probando-bing-el-nuevo-buscador-de-microsoft.html#comments</comments>
		<pubDate>Mon, 01 Jun 2009 14:25:51 +0000</pubDate>
		<dc:creator>Ruben Cantón</dc:creator>
				<category><![CDATA[betatester]]></category>
		<category><![CDATA[informatica]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[laboratorio]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[seo]]></category>

		<guid isPermaLink="false">http://www.entrecodigos.com/?p=1146</guid>
		<description><![CDATA[Aunque la salida oficial de Bing no será hasta dentro de 2 días, el nuevo buscador de Microsoft ya está disponible en versión Beta para quienes queramos empezar a chafardear un poco.

Dejando de lado cuestiones de usabilidad y diseño, he preferido probar su motor de búsqueda para intentar vislumbrar el potencial técnico de este nuevo [...]]]></description>
			<content:encoded><![CDATA[<p>Aunque la salida <strong>oficial</strong> de <strong>Bing</strong> no será hasta dentro de 2 días, el nuevo buscador de <strong>Microsoft</strong> ya está disponible en versión Beta para quienes queramos empezar a chafardear un poco.</p>
<p><img src="http://img34.imageshack.us/img34/526/bingq.jpg" class="aligncenter" alt="Bing, nuevo buscador de Microsoft" /></p>
<p>Dejando de lado cuestiones de usabilidad y diseño, he preferido probar su motor de búsqueda para intentar vislumbrar el potencial técnico de este nuevo buscador que, siendo desconfiado, me da que sigue siendo el mismo Live Search con un lavado de cara, <strong>¿Me equivocaré?</strong></p>
<p><span id="more-1146"></span>Para ser lo más objetivo posible, voy a repetir el <a href="http://www.entrecodigos.com/2007/10/yahoo-es-mejor-que-google-y-msn-live.html">test de evaluación de buscadores</a> que realicé hace año y medio:</p>
<h2>Prueba 1: Buscar términos genéricos</h2>
<p><em>Palabras clave: Guerra civil española</em><br />
Resultados prácticamente idénticos, con la diferencia de que Bing no le da el primer puesto a la wikipedia.</p>
<h2>Prueba 2: Buscar términos comerciales.</h2>
<p><em>Palabras clave: pisos en barcelona</em><br />
Resultados muy parecidos a los de Yahoo, no tanto a los de Google. Pero resulta difícil evaluar la calidad de los mismos dada la enorme optimización SEO que tienen todos esos sitios. Por cierto, que pisos.com sale en primera página de todos ellos.</p>
<h2>Prueba 3: Buscar datos específicos y difíciles.</h2>
<p><em>Palabras clave: Ruben Canton</em><br />
He querido realizar la misma prueba que en la otra ocasión ya que fue aquí en donde fallaron Yahoo y MSN Search. En esta ocasión los resultados han sido mucho más acertados, también hay que decir que han tenido año y medio para indexarlos y a día de hoy es mucho más fácil indexar páginas, pero lo cierto es que han mejorado.</p>
<h2>Prueba 4: Buscando imágenes.</h2>
<p><em>Palabras clave: Parlamento europeo, Howard Gardner, Camara Digital Canon</em><br />
En la primera búsqueda Yahoo falla bastante, mientras el resto te muestran muchos resultados correctos y variados. Lo sorprendente llega en la segunda búsqueda, Bing le da prioridad a los retratos que a los artículos que hablan de Howard, <strong>superando con creces los resultados de Google o Yahoo</strong>. Pero si con eso no tenías bastante esperad que aun llega lo mejor, si buscamos &#8220;Camara Digital Canon&#8221; no sólo nos muestra muy buenos resultados sino que además <a href="http://www.bing.com/images/search?q=Camara%20Digital%20Canon">nos permite filtrar por una serie de características</a> (tamaño, color, diseño, estilo, &#8230;) <strong>increíble!!!</strong></p>
<p><img src="http://img199.imageshack.us/img199/5439/bingcamaras.jpg" class="aligncenter" alt="Bing, nuevo buscador de Microsoft" /></p>
<p><strong>Importante</strong>: Aquí es donde hay que darle otra <strong>medalla para Microsoft</strong>, su buscador de imágenes utiliza <del datetime="2009-06-03T05:19:21+00:00">la tecnología AJAX</del> JavaScript para mostrarte todas las imágenes en una sola página, que se van cargando conforme desplazas el scroll, mientras que Google o Yahoo tienen el incómodo sistema de páginas que te obliga a realizar muchos clicks y es mas lento.</p>
<h2>Prueba 5: Nos vamos de compras&#8230;</h2>
<p><em>Palabras clave: camara digital canon</em><br />
Bueno, aquí si me siento algo decepcionado y estafado. Google no ofrece este servicio, Yahoo redirige tu búsqueda a Kelkoo y Bing la redirije a Ciao&#8230; sinceramente, <strong>no era esto lo que me esperaba</strong>, sino más bien un servicio de crawling de las webs de venta más punteras capaz de mostrarte los artículos que hay en todas ellas a la vez, incluyendo precios!! Eso sí sería algo que valga la pena&#8230; <strong>para buscar en ciao no necesito a Bing</strong>.</p>
<h2>Conclusiones</h2>
<p>Aunque quizás las búsquedas de palabras están más igualadas a día de hoy (o eso o yo no he sabido realizar buenas pruebas), <strong>la búsqueda de imágenes es descaradamente superior en Bing</strong>, respecto a lo de compras&#8230; creo que tendremos que esperar hasta que ese servicio tenga una utilidad real. En todo caso, mis malos augurios respecto a Bing desaparecen, este buscador realmente tiene potencial, o por lo menos, su buscador de imágenes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.entrecodigos.com/2009/06/probando-bing-el-nuevo-buscador-de-microsoft.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Iniciación a LINQ en ASP.Net</title>
		<link>http://www.entrecodigos.com/2009/05/iniciacion-a-linq-en-aspnet.html</link>
		<comments>http://www.entrecodigos.com/2009/05/iniciacion-a-linq-en-aspnet.html#comments</comments>
		<pubDate>Mon, 11 May 2009 14:22:29 +0000</pubDate>
		<dc:creator>Ruben Cantón</dc:creator>
				<category><![CDATA[informatica]]></category>
		<category><![CDATA[laboratorio]]></category>
		<category><![CDATA[taller]]></category>
		<category><![CDATA[tecnologia]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[linq]]></category>
		<category><![CDATA[programacion]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.entrecodigos.com/?p=1086</guid>
		<description><![CDATA[
Tras echarle un primer vistazo a LINQ hace unos meses finalmente me he puesto a darle caña a esta nueva tecnología desarrollada por Microsoft y que pretende facilitarnos las tareas a los desarrolladores.
¿Qué es LINQ?
LinQ (Language Integrated Query) es una nueva librería que se integra en Visual Studio 2008 y permite gestionar colecciones de datos [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://img5.imageshack.us/img5/6633/linqbanner.jpg" alt="LinQ Microsoft" class="aligncenter" /><br />
Tras echarle un primer vistazo a LINQ hace unos meses finalmente me he puesto a darle caña a esta nueva tecnología desarrollada por Microsoft y que pretende facilitarnos las tareas a los desarrolladores.</p>
<h2>¿Qué es LINQ?</h2>
<p>LinQ (Language Integrated Query) es una nueva librería que se integra en Visual Studio 2008 y permite gestionar colecciones de datos de forma más directa utilizando un lenguaje similar al de SQL. Las colecciones de datos pueden proceder de un simple array, una base de datos relacional, un listado de objetos en caché, un archivo XML u orígenes de datos de terceros.</p>
<h2>¿Cómo se usa LINQ?</h2>
<p>Lo mejor para ver esto es poner un ejemplo de cómo se hacían antes las cosas y cómo pueden hacerse ahora gracias a LINQ: </p>
<p><span id="more-1086"></span>Pongamos que por ejemplo tenemos una BDD de alumnos con la tabla TAlumnos y los campos Nombre, Nota y Aprobado por simplificar. Pongamos que nuestro proyecto realiza el 90% de las consultas a esa tabla, y el 70% son simples selects para mostrar datos. Como queremos ahorrarnos cientos de accesos a la BDD (abrir conexión, realizar consulta, cerrar conexión) realizamos una carga inicial de todos esos datos en caché, guardándolo todo en memoria a través de un listado de objetos definidos por la clase CAlumno de propiedades Nombre, Nota y Aprobado.</p>
<p>Imaginemos ahora que quiero consultar los alumnos que han aprobado, y para evitar acceder a la BDD y aprovechando que están en caché hago lo siguiente:</p>
<pre>
        Dim aprobados As New Collections.Generic.List(Of CAlumno)
        For Each alum As CAlumno In Cache.getAlumnos()
            If alum.Aprobado = True Then
                aprobados.Add(alum)
            End If
        Next
</pre>
<p>Aunque supongo que ya se entiende, Cache.getAlumnos devuelve una lista de objetos CAlumno. Por otro lado, meto los aprobados en una lista para luego insertarlos en un GridView sin problemas. Ahora veamos cómo hacer eso mismo con LINQ:</p>
<pre>
Dim aprobados As New Collections.Generic.List(Of CAlumno)
aprobados = From alum In Cache.getAlumnos() Where alum.Aprobado = True
</pre>
<p>Básicamente la sintaxis que lo inicia todo es &#8220;FROM&#8221; tras eso se coloca el origen y se le pueden añadir distintas cláusulas como &#8220;DISTINCT&#8221;, &#8220;WHERE&#8221;, &#8220;ORDER BY&#8221;, &#8220;GROUP BY&#8221;, &#8220;HAVING&#8221;, &#8220;JOIN&#8221;, &#8220;UNION&#8221;, etc y al final un &#8220;SELECT&#8221; en caso de que sólo queramos coger ciertos campos. Si en el caso anterior sólo quisiéramos los nombres:</p>
<pre>
Dim aprobados As String()
aprobados = From alum In Cache.getAlumnos() Where alum.Aprobado = True SELECT alum.Nombre
</pre>
<p>Más allá de la simplificación de código, mi pregunta ahora es&#8230; <strong>¿qué resulta más eficiente?</strong> ¿Qué consume menos recursos o tiempo de proceso? Pues bien, lo mejor para esto es realizar un test de velocidad accediendo a los datos de un XML en LINQ y de la forma tradicional, pero otro día, que por hoy ya tenemos bastante.</p>
<p>Para quien quiera saber más sobre LINQ le recomiendo <a href="http://geeks.ms/blogs/jorge/archive/2007/12/05/aprendiendo-linq-para-visual-basic-2008.aspx">este post de Jorge Serrano</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.entrecodigos.com/2009/05/iniciacion-a-linq-en-aspnet.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Probando la Beta de Unience</title>
		<link>http://www.entrecodigos.com/2008/11/probando-la-beta-de-unience.html</link>
		<comments>http://www.entrecodigos.com/2008/11/probando-la-beta-de-unience.html#comments</comments>
		<pubDate>Fri, 28 Nov 2008 14:53:49 +0000</pubDate>
		<dc:creator>Ruben Cantón</dc:creator>
				<category><![CDATA[betatester]]></category>
		<category><![CDATA[economia]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[laboratorio]]></category>
		<category><![CDATA[web 2.0]]></category>
		<category><![CDATA[beta]]></category>

		<guid isPermaLink="false">http://www.entrecodigos.com/?p=679</guid>
		<description><![CDATA[
Hace sólo unos minutos que he recibido la invitación a Unience, una red social para inversores, y aunque yo no sea un gran inversor mi curiosidad me ha aconsejado invertir un poco de mi tiempo en echarle un vistazo a un proyecto con tendencia alcista aunque de momento no ofrezca dividendos.
Escribo éstas palabras conforme doy [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter" src="http://www.entrecodigos.com/imagenes/logo-unience.gif" alt="Logo Unience" /><br />
Hace sólo unos minutos que he recibido la invitación a <a href="https://www.unience.com">Unience</a>, una <strong>red social para inversores</strong>, y aunque yo no sea un gran inversor mi curiosidad me ha aconsejado <em>invertir </em>un poco de mi tiempo en echarle un vistazo a un proyecto con <em>tendencia alcista</em> aunque de momento no ofrezca <em>dividendos</em>.</p>
<p><img src="http://img46.imageshack.us/img46/6961/betatesteryv5.gif" class="alignright" alt="BetaTester" />Escribo éstas palabras conforme doy mis primeros pasos, empezamos por el <strong>formulario de registro</strong>, muy ergonómico, en que quizás sobraba pedir nombre y apellidos reales o la fecha de nacimiento (sí, sé para qué lo piden, hay que segmentar la BD, pero como usuario me resulta incómodo).</p>
<p>Tras esto volvemos a la Home y me encuentro 4 secciones, diré lo que opino sin entrar en ellas, lo primero, el texto largo al pasar por encima el ratón está muy forzado (se come los márgenes), lo redondearía un poco y lo acortaría, en menos se puede decir más, puede que incluso no sea necesario.<br />
<span id="more-679"></span></p>
<ol>
<li><strong>Seccion 1: Gestiona tus verdaderas inversiones</strong>: Mi primera impresión es que me da miedo, me pide datos para conectarse a mi banco y ver mis inversiones de forma que yo pueda seguirlas en directo. ¿En serio creen que voy a hacer eso? Ni loco!!</li>
<li><strong>Comparte tus conocimientos</strong>: Ésta si resulta interesante, opciones de blogging y comunicación.</li>
<li><strong>Compara tus carteras</strong>: Seguramente la sección mas interesante, poder ver las carteras de otros y aprender de lo que hacen. Transparencia absoluta para cuando un &#8220;experto&#8221; te diga que inviertas en Telecinco cuando él se ha salido o porque él se quedó pillado al comprar hace unos meses.</li>
<li><strong>¡Y es gratis!</strong>: No esperaba lo contrario&#8230; <img src='http://www.entrecodigos.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </li>
</ol>
<p>Sigo adelante y decido ver de qué opciones dispongo. <strong>El área privada</strong> me encanta, tienes todos los módulos sueltos y personalizables con &#8220;drag and drop&#8221;, de forma que puedes poner a tu gusto las cosas que quieres ver y en el orden que prefieras para trabajar. Una cosa curiosa, no puedo poner mi foto, aunque me dejan elegir entre 6 o 7 avatares.</p>
<p>Escribo un post en <strong>el Blog</strong> y veo que dispongo de muy pocas opciones y no es personalizable. Quizás sería mejor dar la opción de poner el feed de tu propio blog, como en FaceBook, y que se vaya publicando automáticamente.</p>
<p>Quiero volver a la Home (donde las 4 secciones) y me encuentro con que <strong>ningún enlace me lleva allí</strong> excepto uno que me lleva a una zona que parece mas bien publicitaria. Cuando por fin consigo entrar en las secciones veo que casi todo es publicitario y no puedo chafardear las acciones de los demás&#8230; ¡Muy mal! =(</p>
<p><img src="http://img399.imageshack.us/img399/6734/gentezd5.gif" class="aligncenter" alt="Red social" /></p>
<p>En general, <strong>la idea de la red social es buena</strong>. Si un inversor sabe hacer buenas inversiones y es capaz de ganar dinero no debe importarle mostrar al resto sus habilidades, ésto podría permitirle hacer muy buenos contactos y conseguir buenas oportunidades laborales. Sin embargo, para confirmar que realmente ésas son sus inversiones parece necesario ofrecer una serie de datos que yo, por lo menos, no estoy dispuesto a dar.</p>
<p>Por otro lado, la herramienta está muy bien hecha, es cierto que si buscas criticar podrás hacerlo, para gustos&#8230; pero me ha parecido <strong>un portal muy estable y con mucho potencial</strong>, yo lo abriría aun más en el futuro, permitiendo enlazarlo con tu blog, tu feed de Twitter e incluso otras redes sociales como Facebook.</p>
<p>Para el tema de los datos bancarios, <strong>¿existiría la posibilidad de que los bancos pongan un servicio de feed para realizar estas consultas?</strong> Sería una forma de evitar tener que dar datos demasiado sensibles.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.entrecodigos.com/2008/11/probando-la-beta-de-unience.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Primeros pasos en Google Chrome</title>
		<link>http://www.entrecodigos.com/2008/09/primeros-pasos-en-google-chrome.html</link>
		<comments>http://www.entrecodigos.com/2008/09/primeros-pasos-en-google-chrome.html#comments</comments>
		<pubDate>Wed, 03 Sep 2008 07:45:56 +0000</pubDate>
		<dc:creator>Ruben Cantón</dc:creator>
				<category><![CDATA[google]]></category>
		<category><![CDATA[informatica]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[laboratorio]]></category>
		<category><![CDATA[tecnologia]]></category>

		<guid isPermaLink="false">http://www.entrecodigos.com/?p=241</guid>
		<description><![CDATA[Escribo esto desde Google Chrome 0.2, el nuevo explorador de Internet lanzado por Google en fase Beta (la primera duda es: ¿dejará de estar en beta algún día?) y cuya versión es la siguiente:
Build oficial 1583
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13
En la página de presentación se nos muestran [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://img170.imageshack.us/img170/9885/chromelogoyf5.jpg" class="alignright" /><strong>Escribo esto desde Google Chrome 0.2</strong>, el nuevo explorador de Internet lanzado por Google en fase Beta (la primera duda es: ¿dejará de estar en beta algún día?) y cuya versión es la siguiente:</p>
<pre>Build oficial 1583
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13</pre>
<p>En la <a href="http://tools.google.com/chrome/intl/es/features.html">página de presentación</a> se nos muestran mas cosas acerca de Chrome, muchas de ellas ya se explicaban en <a href="http://www.google.com/googlebooks/chrome/" target="_blank">el cómic que pudimos ver ayer</a>, creo que una de las cosas que no comenté fueron las mejoras en seguridad que incorpora Chrome, impidiendo que las pestañas tengan permisos para acceder al contenido de otra o al contenido de tu PC, por ejemplo; aunque advertían que<strong> los plugins pueden saltarse los controles de seguridad</strong>, por lo que habrá que tener cuidado con lo que instalamos.</p>
<div style="text-align:center;"><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/9GLrAAChKRQ&#038;hl=en&#038;fs=1&#038;rel=0"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/9GLrAAChKRQ&#038;hl=en&#038;fs=1&#038;rel=0" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object></div>
<p>En general, me ha gustado mucho todo lo que he visto de Google Chrome, me pondré a utilizarlo y ya veremos que tal funciona con el tiempo, de momento, supera el <a href="http://www.webstandards.org/files/acid2/test.html#top">test Acid 2</a> y <a href="http://www.css3.info/selectors-test/test.html">CSS Selectors</a> sin ningún problema, aunque el <a href="http://acid3.acidtests.org/">Acid 3</a> se le ha atragantado un poquillo (63/100 frente a 57/100 de Firefox); por lo que <strong>Chrome es el explorador que mejor cumple los estándares</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.entrecodigos.com/2008/09/primeros-pasos-en-google-chrome.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aparece Google Chrome</title>
		<link>http://www.entrecodigos.com/2008/09/aparece-google-chrome.html</link>
		<comments>http://www.entrecodigos.com/2008/09/aparece-google-chrome.html#comments</comments>
		<pubDate>Tue, 02 Sep 2008 12:33:32 +0000</pubDate>
		<dc:creator>Ruben Cantón</dc:creator>
				<category><![CDATA[habitatsoft]]></category>
		<category><![CDATA[informatica]]></category>
		<category><![CDATA[inmobiliaria]]></category>
		<category><![CDATA[laboratorio]]></category>
		<category><![CDATA[personal]]></category>
		<category><![CDATA[politica]]></category>
		<category><![CDATA[seo]]></category>

		<guid isPermaLink="false">http://www.entrecodigos.com/?p=229</guid>
		<description><![CDATA[Hoy es mi  cumpleaños, y para celebrarlo -llamadme egocentrista-, Google ha lanzado su  explorador de Internet llamado Chrome con el que piensa robarle tráfico a  Microsoft -aunque dado como va MSN Live Search, tampoco parece que les haga  mucha falta-.
El nuevo explorador pinta muy bien si nos dejamos llevar por la [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Hoy es mi  cumpleaños</strong>, y para celebrarlo -llamadme egocentrista-, Google ha lanzado su  explorador de Internet llamado <strong>Chrome</strong> con el que piensa robarle tráfico a  Microsoft -aunque dado como va MSN Live Search, tampoco parece que les haga  mucha falta-.</p>
<p>El nuevo explorador pinta muy bien si nos dejamos llevar por la campaña marketiniana googlera <a title="Google Chrome comic" href="http://www.google.com/googlebooks/chrome/" target="_blank">plasmada en este cómic</a>, entre otras cosas, <strong>separa cada pestaña en un proceso distinto</strong>, lo que consume más memoria (el argumento googliano de la fragmentación de la misma en el largo plazo y los punteros vacíos no me convence ya que también podrían haber hecho un sistema de limpieza de la memoria mas optimizado) pero tiene otras ventajas como no perder todas las pestañas si una se colapsa o seguir trabajando con otras mientras una trabaja.</p>
<p>Al igual que Firefox, Google ha prestado mucha atención a la velocidad de ejecución de JavaScript y con eso en mente <strong>han desarrollado la máquina virtual V8</strong>, que entre otras cosas, parece que compilará el JS directamente a código máquina para que se ejecute más rápido en vez de interpretarlo. Esto permitirá que páginas como GMail se ejecuten más rápidamente.</p>
<p>No obstante, <strong>una de las mejores cosas que veo</strong> que piensa incorporar es una especie de &#8220;Administrador de tareas&#8221; del explorador que te informe de cuántos recursos está consumiendo cada pestaña y cada complemento, de forma que si Chrome te va lento o consume mucha RAM puedas saber el motivo y &#8220;matar&#8221; el proceso que incordia (o desinstalar el plugin de turno).</p>
<p>También incluye otra mejora muy interesante, al abrir una nueva pestaña, la página inicial que se te abre te mostrará las 9 páginas que mas visitas y tus buscadores más utilizados.</p>
<p>Ya estoy deseando probar que tal funciona y <strong>cuál es su interpretación de los estándares</strong>, aunque me toca esperar, ya que según he leído por ahí, <strong>se podrá descargar hoy mismo en cuanto se levanten los estadounidenses</strong>, que siempre son los últimos. =P</p>
<p><strong>Actualización</strong>: Se podrá descargar a partir de las 4 de la mañana de esta misma noche hora española.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.entrecodigos.com/2008/09/aparece-google-chrome.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>¿Cómo funcionan el StartsWith, Contains o EndsWith?</title>
		<link>http://www.entrecodigos.com/2008/05/startswith-contains-endswith-aspnet.html</link>
		<comments>http://www.entrecodigos.com/2008/05/startswith-contains-endswith-aspnet.html#comments</comments>
		<pubDate>Sat, 31 May 2008 09:14:09 +0000</pubDate>
		<dc:creator>Ruben Cantón</dc:creator>
				<category><![CDATA[laboratorio]]></category>
		<category><![CDATA[taller]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://www.entrecodigos.com/2008/05/startswith-contains-endswith-aspnet.html</guid>
		<description><![CDATA[En .Net tenemos una función llamada StartsWith para saber si un String comienza con una serie de caracteres determinados, en principio, yo me imagino que si dicha función determina que el primer carácter ya no coincide dejará de comparar el resto y devolverá un false, no obstante he querido comprobar si eso es cierto comparando [...]]]></description>
			<content:encoded><![CDATA[<p>En .Net tenemos una función llamada <strong>StartsWith</strong> para saber si un String comienza con una serie de caracteres determinados, en principio, yo me imagino que si dicha función determina que el primer carácter ya no coincide dejará de comparar el resto y devolverá un false, no obstante he querido comprobar si eso es cierto comparando cuánto tarda con un String con el que si empieza, con otro con el que no empieza o con uno con el que coincide a medias; y para que no haya dudas, un poco a lo bestia&#8230; <strong>metiéndolo en un bucle de 5 millones de pasadas</strong>.</p>
<table class="tablaFina" cellpadding="1" cellspacing="0">
<tr style="text-align:center;font-weight:bold;">
<td>Bucle</td>
<td>Segundos</td>
</tr>
<tr>
<td>StartsWith No Coincidente</td>
<td class="alignRight">1,789597</td>
</tr>
<tr>
<td>StartsWith Casi Coincidente</td>
<td class="alignRight">2,186570</td>
</tr>
<tr>
<td>StartsWith Coincidente</td>
<td class="alignRight">0,081005</td>
</tr>
</table>
<p>Me sorprende que el coincidente sea el que menos consuma, ¿significa eso que .Net sigue comparando el resto de caracteres? Pero lo que me deja sin explicación alguna es ver que el coincidente a medias es el que más tiempo tarda&#8230; podría pensar que este string es más largo que el anterior y tendría sentido, pero <strong>sería absurdo pensar que el algoritmo StartsWith sigue comparando caracteres aunque ya haya encontrado uno no coincidente&#8230;</strong> ¿No les enseñaron a usar el Exit While?</p>
<p><span id="more-189"></span><strong>Y ya que estoy, lo comparo con el Contains y&#8230;</strong></p>
<table class="tablaFina" cellpadding="1" cellspacing="0">
<tr style="text-align:center;font-weight:bold;">
<td>Bucle</td>
<td>Segundos</td>
</tr>
<tr>
<td>Contains No Coincidente</td>
<td class="alignRight">1,015006</td>
</tr>
<tr>
<td>Contains Casi Coincidente</td>
<td class="alignRight">1,025467</td>
</tr>
<tr>
<td>Contains Coincidente</td>
<td class="alignRight">1,116619</td>
</tr>
</table>
<p>Parece que <strong>el Contains está bastante mejor optimizado</strong>, parece un absurdo ya que el StartsWith lo tiene más fácil, pero los resultados no engañan. Las diferencias en este caso son menores pero se aprecia que el No Coincidente tarda menos que el Coincidente a Medias, que a su vez tarda menos que el Coincidente, lo que daría sentido a la teoría de que deja de comparar chars en cuanto uno rompe la equivalencia. El StarsWith coincidente sí consume menos, pero usarlo conlleva el riesgo de topar con un no coincidente y tardar más.</p>
<p><strong>¿Y el EndsWith? ¿Funcionará igual?</strong></p>
<table class="tablaFina" cellpadding="1" cellspacing="0">
<tr style="text-align:center;font-weight:bold;">
<td>Bucle</td>
<td>Segundos</td>
</tr>
<tr>
<td>EndsWith No Coincidente</td>
<td class="alignRight">3,723053</td>
</tr>
<tr>
<td>EndsWith Casi Coincidente</td>
<td class="alignRight">3,722809</td>
</tr>
<tr>
<td>EndsWith Coincidente</td>
<td class="alignRight">0,081173</td>
</tr>
</table>
<p>Bueno, lo del EndsWith ya resulta hasta triste, no sólo es el que más tarda si no que además vuelve a demostrar que no parece que hayan sabido hacer un algoritmo con lógica. Al ser un EndsWith tendrían que comparar los strings a la inversa, desde atrás hacia adelante, y saliendo del bucle en cuanto encontrase el primer char no coincidente, pero por los resultados obtenidos mas parece que se ponga a buscar a Wally y a tomarse una cerveza por el camino&#8230; ahora sólo faltaría hacer lo mismo en C# para ver si funciona mejor, de hacerlo, el mito del C# resultaría cierto&#8230; pero creo que no me atrevo a desmitificar mi querido Visual Basic. <strong>Oh Microsoft, ¿por qué nos has abandonado?</strong></p>
<p>Aquí va el código por si queréis verlo por vosotros mismos o podéis encontrar en dónde me he equivocado para obtener estos incomprensibles resultados (que dado que ya me equivoqué con el experimento del otro día, no sería nada raro):</p>
<pre style="height:200px;">
  Private Sub PruebaRendimiento_StartsWith()
        Dim i As Double
        Dim META As Double = 5000000

        Dim strPalabra As String = "escalifragilisticoespialidoso"
        Dim strCoincide As String = "escalifragilisticoespialidoso"
        Dim strCoincidenteAMedias As String = "escalifragilistPosVaSerQueNo"
        Dim strNoCoincide As String = "PosVaSerQueNo"

        Me.Trace.IsEnabled = True
        Me.Trace.Warn("PRUEBA DE RENDIMIENTO. START:")

        '**************************
        'STARTSWITH:

        'No
        Me.Trace.Warn("Empiezo bucle StartsWith no coincidente.")
        For i = 0 To META
            If strPalabra.StartsWith(strNoCoincide) Then
            End If
        Next
        Me.Trace.Warn("Bucle StartsWith no coincidente terminado.____________________________")

        'Casi
        Me.Trace.Warn("Empiezo bucle StartsWith casi coincidente.")
        For i = 0 To META
            If strPalabra.StartsWith(strCoincidenteAMedias) Then
            End If
        Next
        Me.Trace.Warn("Bucle StartsWith casi coincidente terminado.____________________________")

        'Si
        Me.Trace.Warn("Empiezo bucle StartsWith coincidente.")
        For i = 0 To META
            If strPalabra.StartsWith(strCoincide) Then
            End If
        Next
        Me.Trace.Warn("Bucle StartsWith coincidente terminado.____________________________")

        '**************************
        'CONTAINS:

        'No
        Me.Trace.Warn("Empiezo bucle Contains no coincidente.")
        For i = 0 To META
            If strPalabra.Contains(strNoCoincide) Then
            End If
        Next
        Me.Trace.Warn("Bucle Contains no coincidente terminado.____________________________")

        'Casi
        Me.Trace.Warn("Empiezo bucle Contains casi coincidente.")
        For i = 0 To META
            If strPalabra.Contains(strCoincidenteAMedias) Then
            End If
        Next
        Me.Trace.Warn("Bucle Contains casi coincidente terminado.____________________________")

        'Si
        Me.Trace.Warn("Empiezo bucle Contains coincidente.")
        For i = 0 To META
            If strPalabra.Contains(strCoincide) Then
            End If
        Next
        Me.Trace.Warn("Bucle Contains coincidente terminado.____________________________")

        '**************************
        'ENDSWITH:
        strCoincidenteAMedias = "PosNoticoespialidoso"

        'No
        Me.Trace.Warn("Empiezo bucle EndsWith no coincidente.")
        For i = 0 To META
            If strPalabra.EndsWith(strNoCoincide) Then
            End If
        Next
        Me.Trace.Warn("Bucle EndsWith no coincidente terminado.____________________________")

        'Casi
        Me.Trace.Warn("Empiezo bucle EndsWith casi coincidente.")
        For i = 0 To META
            If strPalabra.EndsWith(strCoincidenteAMedias) Then
            End If
        Next
        Me.Trace.Warn("Bucle EndsWith casi coincidente terminado.____________________________")

        'Si
        Me.Trace.Warn("Empiezo bucle EndsWith coincidente.")
        For i = 0 To META
            If strPalabra.EndsWith(strCoincide) Then
            End If
        Next
        Me.Trace.Warn("Bucle EndsWith coincidente terminado.____________________________")

    End Sub
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.entrecodigos.com/2008/05/startswith-contains-endswith-aspnet.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>String Builder vs String en ASP.Net</title>
		<link>http://www.entrecodigos.com/2008/05/stringbuilder-vs-string.html</link>
		<comments>http://www.entrecodigos.com/2008/05/stringbuilder-vs-string.html#comments</comments>
		<pubDate>Thu, 29 May 2008 18:46:52 +0000</pubDate>
		<dc:creator>Ruben Cantón</dc:creator>
				<category><![CDATA[laboratorio]]></category>
		<category><![CDATA[taller]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://www.entrecodigos.com/2008/05/stringbuilder-vs-string.html</guid>
		<description><![CDATA[Como ya dije hace unos días, ando algo liado últimamente, aunque también puede que sea que necesito respirar un poco de aire fresco y hacer cosas distintas, por lo que temporalmente voy a pasarme poco por el blog. No obstante os traigo un pequeño experimento que hice el otro día en ASP.Net, en donde a [...]]]></description>
			<content:encoded><![CDATA[<p>Como ya dije hace unos días, ando algo liado últimamente, aunque también puede que sea que necesito respirar un poco de aire fresco y hacer cosas distintas, por lo que temporalmente voy a pasarme poco por el blog. No obstante os traigo un pequeño experimento que hice el otro día en ASP.Net, en donde a través del sistema de trazas <strong>comprobé la eficacia del StringBuilder de .Net</strong>.</p>
<p><strong>¿Stringloqué?</strong> StringBuilder es una clase de .Net que representa un String como un objeto, se encuentra en System.Text y su principal particularidad consiste en un menor consumo de recursos a la hora de formar una cadena de texto (de ahí su nombre). StringBuilder reserva un buffer de memoria de forma que cuando vas a insertar nuevos caracteres mira si el buffer es suficiente, si lo es los mete, si no lo es, amplia el búffer y los mete.</p>
<p>Pero, <strong>¿que hacía entonces el String normal?</strong> El String normal tiene varias formas de ser concatenado, .Concat, .Join, &#8220;+&#8221; y &#8220;&#038;&#8221;. Cada una de ellas distinta pero en principio todas iguales, la idea, y a menos que alguien me corrija y me saque del error, es que crea un nuevo objeto a partir de los ya existentes (un nuevo string), lo que parece consumir bastante mas RAM además de tiempo de proceso.</p>
<p>Yo, por curiosidá de esa que sólo un frikie informático tiene y por culpa de la cual nos consideran un reducto mutante de la sociedad (nosotros nos creemos pr0s) decidí generar un algoritmo facilón y activar el sistema de trazas para realizar carreras&#8230; <strong>¿Queréis saber quien gana?</strong></p>
<p><span id="more-188"></span>Primero que todo <strong>os muestro el código fuente</strong>, por si alguien ve algún error en el mismo que pueda haber alterado los resultados:</p>
<pre style="height:250px;">
    Private Sub PruebaRendimiento()
        Dim i As Integer
        Dim strTest As String = ""
        Dim strTestBuilder As New StringBuilder
        Dim META As Integer = 50000
        Dim arrStrings() As String = {""}

        Me.Trace.IsEnabled = True
        Me.Trace.Warn("PRUEBA DE RENDIMIENTO. START:")

        'STRING +
        Me.Trace.Warn("Empiezo bucle con String +.")
        For i = 0 To META
            strTest += i.ToString
        Next
        Me.Trace.Warn("Bucle con String + terminado.____________________________")

        'STRING &#038;
        strTest = ""
        Me.Trace.Warn("Empiezo bucle con String &#038;.")
        For i = 0 To META
            strTest = strTest &#038; i.ToString
        Next
        Me.Trace.Warn("Bucle con String &#038; terminado.____________________________")

        'STRING CONCAT
        strTest = ""
        Me.Trace.Warn("Empiezo bucle con String CONCAT.")
        For i = 0 To META
            strTest = String.Concat(strTest, i.ToString)
        Next
        Me.Trace.Warn("Bucle con String CONCAT terminado.____________________________")

        'STRING JOIN
        strTest = ""
        Me.Trace.Warn("Empiezo bucle con String JOIN.")
        For i = 0 To META
            Array.Resize(arrStrings, arrStrings.Length + 1)
            arrStrings.SetValue(i.ToString, arrStrings.Length - 1)
        Next
        strTest = String.Join("", arrStrings)
        Me.Trace.Warn("Bucle con String JOIN terminado.____________________________")

        'STRING BUILDER
        strTest = ""
        Me.Trace.Warn("Empiezo bucle con StringBuilder.")
        For i = 0 To META
            strTestBuilder.Append(i.ToString)
        Next
        Me.Trace.Warn("Bucle con StringBuilder terminado.____________________________")

    End Sub
</pre>
<p>Tras lo cual, hice 3 pruebas, una facililla de 5 vueltas al bucle, otra algo mas dura con 5000 y finalmente la bestia negra que casi tumba al .Net con 50.000 (y no quiero ni saber cuánto ocupaba ese string). <strong>Aquí tenéis los resultados:</strong></p>
<table class="tablaFina" cellpadding="1" cellspacing="0">
<tr style="text-align:center;font-weight:bold;">
<td>Bucle</td>
<td>META</td>
<td>Segundos</td>
</tr>
<tr>
<td>String +</td>
<td class="alignCenter">5</td>
<td class="alignRight">0,000032</td>
</tr>
<tr>
<td>String &#038;</td>
<td class="alignCenter">5</td>
<td class="alignRight">0,000029</td>
</tr>
<tr>
<td>String CONCAT</td>
<td class="alignCenter">5</td>
<td class="alignRight">0,000029</td>
</tr>
<tr>
<td>String JOIN</td>
<td class="alignCenter">5</td>
<td class="alignRight">0,000036</td>
</tr>
<tr>
<td>StringBuilder</td>
<td class="alignCenter">5</td>
<td class="alignRight">0,000028</td>
</tr>
<tr>
<td>String +</td>
<td class="alignCenter">50</td>
<td class="alignRight">0,111021</td>
</tr>
<tr>
<td>String &#038;</td>
<td class="alignCenter">50</td>
<td class="alignRight">0,303108</td>
</tr>
<tr>
<td>String CONCAT</td>
<td class="alignCenter">50</td>
<td class="alignRight">0,842379</td>
</tr>
<tr>
<td>String JOIN</td>
<td class="alignCenter">50</td>
<td class="alignRight">0,128027</td>
</tr>
<tr>
<td>StringBuilder</td>
<td class="alignCenter">50</td>
<td class="alignRight">0,003752</td>
</tr>
<tr>
<td>String +</td>
<td class="alignCenter">50000</td>
<td class="alignRight">25,125145</td>
</tr>
<tr>
<td>String &#038;</td>
<td class="alignCenter">50000</td>
<td class="alignRight">78,670144</td>
</tr>
<tr>
<td>String CONCAT</td>
<td class="alignCenter">50000</td>
<td class="alignRight"><strong>146,204513</strong></td>
</tr>
<tr>
<td>String JOIN</td>
<td class="alignCenter">50000</td>
<td class="alignRight">27,010910</td>
</tr>
<tr>
<td>StringBuilder</td>
<td class="alignCenter">50000</td>
<td class="alignRight"><strong>0,046688</strong></td>
</tr>
</table>
<h2>Nota: Estas conclusiones las saqué bajo un error, los datos reales están más abajo</h2>
<p>En principio no existen demasiadas diferencias entre las pruebas, el tiempo aumenta a la vez que lo hace la variable META, no obstante, <strong>al CONCAT y al &#038; se les ha atragantado muchísimo la bestia negra</strong> mientras que StringBuilder ni se ha inmutado. <strong>StringBuilder es el ganador indiscutible</strong> y supera a todos los demás en todas las pruebas con una mayor velocidad de concatenación, pero claro, eso era lo que se esperaba de él&#8230; ¿no? (Hay que ver que poca fe tenéis en Microsoft&#8230;).</p>
<p>La sorpresa me ha llegado del Concat y del &#038;, por un lado, el &#038; no debería tener tantos problemas al concatenar dos cadenas, o cuanto menos debería tener menos problemas que un + que se puede utilizar para mas cosas, pero sobretodo, <strong>sorprende ver cómo el .Concat es el perdedor absoluto de esta carrera de concatenaciones</strong>, y eso que se supone que el método fue creado para algo&#8230; no parece que fuera para hacer códigos optimizados.</p>
<p>El resto de conclusiones podéis sacarlas vosotros mismos, eso sí, con cadenas se pueden hacer mas cosas, como replaces, substrings, remove, copy, &#8230; habría que ver una a una quién resulta mas eficiente, <strong>¿alguien se anima?</strong></p>
<h2>Actualización</h2>
<p>Parece ser que <strong>se me olvió limpiar la variable strTest tras cada bucle</strong>, con lo que los resultados anteriores estaban adulterados y eran erróneos. Tras rectificar el pequeño problemilla estos son los resultados de la bestia negra:</p>
<table class="tablaFina" cellpadding="1" cellspacing="0">
<tr style="text-align:center;font-weight:bold;">
<td>Bucle</td>
<td>META</td>
<td>Segundos</td>
</tr>
<tr>
<td>String +</td>
<td class="alignCenter">50000</td>
<td class="alignRight">50,524726</td>
</tr>
<tr>
<td>String &#038;</td>
<td class="alignCenter">50000</td>
<td class="alignRight">49,690219</td>
</tr>
<tr>
<td>String CONCAT</td>
<td class="alignCenter">50000</td>
<td class="alignRight">49,919286</td>
</tr>
<tr>
<td>String JOIN</td>
<td class="alignCenter">50000</td>
<td class="alignRight">23,218603</td>
</tr>
<tr>
<td>StringBuilder</td>
<td class="alignCenter">50000</td>
<td class="alignRight"><strong>0,041889</strong></td>
</tr>
</table>
<p><strong><br />
El ganador indiscutible sigue siendo el StringBuilder</strong>, el Join no se vio muy afectado por el error del algoritmo por ser un array y los demás son prácticamente idénticos, así que ya podré volver a usar el &#038; como de costumbre&#8230; <img src='http://www.entrecodigos.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Espero que quienes leyeran las conclusiones anteriores se lean las nuevas y no vivan pensando que el .Concat es el anticristo de la optimización de código. :S Por cierto, que si tenemos en cuenta que el error del algoritmo anterior acumulaba las cadenas bucle a bucle, el StringBuilder, por estar al final, se comía la peor cadena de todas y a pesar de eso ofrecía el mejor rendimiento de todos siendo casi instantáneo, <strong>un /clap bien grande desde aquí a Microsoft</strong> por semejante objeto ultraoptimizado que ponen a nuestra disposición (si, los informáticos decimos /clap, ¿que pasa?).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.entrecodigos.com/2008/05/stringbuilder-vs-string.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
