Con risposta [VB 2010] utilizzo di linq

  • venerdì 13 aprile 2012 14:40
     
      Contiene codice

    ciao a tutti,

    ho iniziato da poco ad usare linq e questa è la prima volta che riesco ad utilizzarlo senza problemi.premetto che ho letto varie dispense riguardanti linq.comunque la mia domanda è la seguente...

    date le seguenti procedure, perchè quella che utilizza linq è molto piu lenta? c'è qualcosa che sbaglio??

    funzione normale: 5.8s

    procedura con utilizzo linq: 12.3s

     Private Function GoodFalseCallsRealError() As String
            Dim TotCallFalseCalls As Integer = 0
            Dim TotCallRealErrors As Integer = 0
            Dim TotCalNotClassified As Integer = 0
            Dim TotCalAlignmentError As Integer = 0
            Dim TotCallFail As Integer = 0
            Dim ArrayGood As New List(Of String)
            Dim ArrayFail As New List(Of String)
    
            For r = 0 To dbgTabella.RowCount - 1
                Select Case dbgTabella(mResult, r).Value.ToString
                    Case mGood 'good
                        If Not ArrayFail.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayGood.Add(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                    Case mFalseCall
                        If ArrayGood.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayGood.Remove(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        If Not ArrayFail.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayFail.Add(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        TotCallFalseCalls += 1
                    Case mRealErrors
                        If ArrayGood.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayGood.Remove(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        If Not ArrayFail.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayFail.Add(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        TotCallRealErrors += 1
                    Case mNotClassified
                        If ArrayGood.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayGood.Remove(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        If Not ArrayFail.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayFail.Add(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        TotCalNotClassified += 1
                    Case mAlignmentError
                        If ArrayGood.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayGood.Remove(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        If Not ArrayFail.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayFail.Add(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        TotCalAlignmentError += 1
                    Case mFail
                        If ArrayGood.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayGood.Remove(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        If Not ArrayFail.Contains(dbgTabella(mSerialNumber, r).Value.ToString) Then
                            ArrayFail.Add(dbgTabella(mSerialNumber, r).Value.ToString)
                        End If
                        TotCallFail += 1
                End Select
            Next
            Return ArrayGood.Count.ToString & ";" & TotCallFalseCalls.ToString & ";" & TotCallRealErrors.ToString & ";" & TotCalNotClassified.ToString & ";" & TotCalAlignmentError.ToString & ";" & TotCallFail.ToString & ";" & ArrayFail.Count.ToString
        End Function
    
    
    Private Sub ProvaToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ProvaToolStripMenuItem.Click
            Dim TotCallFalseCalls As Integer = 0
            Dim TotCallRealErrors As Integer = 0
            Dim TotCalNotClassified As Integer = 0
            Dim TotCalAlignmentError As Integer = 0
            Dim TotCallFail As Integer = 0
            Dim ArrayGood As New List(Of String)
            Dim ArrayFail As New List(Of String)
            Dim seriale As String = String.Empty
    
            For r = 0 To dbgTabella.RowCount - 1
                seriale = dbgTabella(mSerialNumber, r).Value.ToString
                Select Case dbgTabella(mResult, r).Value.ToString
                    Case mGood
                        Dim risp = (From serial As String In ArrayGood Where serial = seriale Select serial).Count
                        If risp = 0 Then
                            ArrayGood.Add(seriale)
                        End If
                    Case mFalseCall, mRealErrors, mNotClassified, mAlignmentError, mFail
                        Dim risp = (From serial As String In ArrayGood Where serial = seriale Select serial).Count
                        If risp > 0 Then
                            ArrayGood.Remove(seriale)
                        End If
                        risp = (From serial As String In ArrayFail Where serial = seriale Select serial).Count
                        If risp = 0 Then
                            ArrayFail.Add(seriale)
                        End If
                        Select Case dbgTabella(mResult, r).Value.ToString
                            Case mGood 'good
    
                            Case mFalseCall
                                TotCallFalseCalls += 1
                            Case mRealErrors
                                TotCallRealErrors += 1
                            Case mNotClassified
                                TotCalNotClassified += 1
                            Case mAlignmentError
                                TotCalAlignmentError += 1
                            Case mFail
                                TotCallFail += 1
                        End Select
                End Select
            Next
            Console.WriteLine(ArrayGood.Count.ToString & ";" & TotCallFalseCalls.ToString & ";" & TotCallRealErrors.ToString & ";" & TotCalNotClassified.ToString & ";" & TotCalAlignmentError.ToString & ";" & TotCallFail.ToString & ";" & ArrayFail.Count.ToString)
        End Sub

Tutte le risposte

  • lunedì 30 aprile 2012 03:21
    Proprietario
     
     

    Ciao X-SL4AUGHT3R,

    Per miglior supporto, ti ho spostato la domanda sul forum dedicato a LINQ.

    Saluti,


    Irina Turcu - Microsoft

    [Manifesto] Regole e Aspetti generali all'uso dei forum MSDN

    Questo contenuto è distribuito “as is” e non implica alcuna responsabilità da parte di Microsoft. L'azienda offre questo servizio gratuitamente, allo scopo di aiutare gli utenti e approfondire la loro conoscenza dei prodotti e tecnologie Microsoft.

    LinkedIn

  • lunedì 30 aprile 2012 09:42
     
     Con risposta

    ciao

    il discorso è complesso :)

    le query linq vengono eseguite ma prima precompilate, quindi in alcuni scenari potrebbero essere meno performanti di un codice procedurale, ma non credo sia il tuo caso

    il tuo caso è poco performante perchè stai approcciando in maniera procedurale l'uso di linq che è invece funzionale

    e poi il .Count su di una collection la materializza e conteggia e quindi è proprio poco performante

    sostituisci i vari .Count con magari un .FirstOrDefault(tua where) == null

    oppure una .All(tua where) che torna già un boolean

    dovresti poi evitare di usare dbgTabella e enumerare a mano sulla Row, prova a lavorare direttamente sul suo DataSource che è sicuramente una collezione o qualcosa di simile facilmente enumerabile ad oggetti sempre tramite LINQ

    il consiglio finale: LINQ come già detto serve per fare una query, cerca di cambiare radicalmente la tua logica in ottica di farti dare direttamente il risultato da un'unica macro query, al posto di iterare a mano con i vari For e fare .Add e .Remove di lentissime liste

    restiamo a disposizione per ogni dubbio

    a presto


    Antonio Esposito [MCT, MCPD, MCTS, MCP]
    dotnetlombardia.org | blog | web | @tonyexpo
    Italy