Testing LINQ performance with ASP.Net

LINQ

This post its a translation from my original post in spanish. I hope you enjoy it! 🙂

After learning the basics about LINQ and how it works, I had no choice but to test if, not only does it simplifies the code but also improves its efficiency.

I decided to test the reading speed of XML files with LINQ and determine which one has a better reading speed: .Net XML access library or its new technology, LINQ. To that purpose, I built an XML with 100.000 registers which simulates a table with students data and I will send some requests.

Those are the requests I’ve decided to do using both systems:

  • Test 1: Extract all the students named Jorge.
  • Test 2: Count how many students have passed.
  • Test 3: Between the students named Jorge, how many have failed?
  • Test 4: Between the students who have take more than an 8, which name its more common?
  • Test 5: Extract the different names of the students and order them alfabethically.

After throwing these requests using the different methods here I have, in seconds, how many time each one has take:

Test XML Reader LINQ
1 0,301934 0,000036
2 0,589991 0,090168
3 0,390582 0,054944
4 0,432305 0,091441
5 0,281885 0,042886

It can be clearly apreciated the difference in access speed, being XML Reader between 7 and 8 times more slower than LINQ. But not enough with that, requests in LINQ have take up between 1 and 3 lines of code (and because I’ve want to divide it into different lines) while the ones made with the old method have take up between 10 and 30 lines of code.

For all this, LINQ seems to beat XML Reader in speed access as well as in code simplifycation, which reduces code errors and cost production or maintenance.

I know there are other methods for accesing an XML file using .Net (the XML library offers more options), but I have decided to use this one, maybe another would have been more efficient, but after making various tests using LINQ it has clearly convinced me as a data access technology.

Finally, I leave here the source code in case someone wants to have a look at it or maybe I’ve made a mistake and you want to warn me 😉

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 <> "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) < 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 < 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) &gt; <img src="http://www.entrecodigos.com/wp-includes/images/smilies/icon_cool.gif" alt="8)" /> _
            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 &gt; 0 And oAlumno.Nombre.Length &gt; 0 Then
                        If oAlumno.Nota &gt; 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) &gt; 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

Leave a Reply

Close Bitnami banner
Bitnami