7
votes

Performance Linq: (Élément, compte) vs (foreach)

i Itérale à l'aide d'un iéenérable à la suite d'une requête LINQ en utilisant (élémat, compte) et (foreach). À ma surprise, la différence de performance est de 25-30 fois! Pourquoi est-ce? XXX


3 commentaires

Quel touriste est la différence (ce qui est plus rapide)?


Count () ira déterrer sur le tout en-téméride. Chaque ellementat (n) irate to the nth élément. TRANCHACH ITERA ITERA TOUT ENUDE ENUMERABLE une fois. Je ne connais pas toutes les optimisations si l'énumérable est également un iList ou icollection .


Vous devriez clairement indiquer quelle méthode était plus rapide


7 Réponses :


6
votes

parce que ollementat code> est itération via le ienumerable code> chaque fois que vous l'appelez. iEnumerable code> s ne sont pas indexés, donc ellementat code> doit être implémenté à l'aide de getenumerator () code>.

Pourquoi ne pas faire p>

total = result.Sum();


3 commentaires

... Comme compte () . Il n'y a pas besoin d'expression de Lambda, BTW. Juste résultat.sum () devrait être bien.


@Jon Skeet, soupçonné donc mais devait aller vérifier en premier. Semble évident maintenant, ALA SELECT ()


Total + = P; est à titre de démonstration. La logique réelle est différente.



1
votes

Parce que chaque appel iTère sur la liste. La solution simple consiste à appeler .tolist () avant itération, une meilleure solution consiste à arrêter itérant. xxx pré>

meilleure solution: p>

total = result.Sum();


0 commentaires

1
votes

La différence de performance est due au fait que le ienumerable ne vous permet pas d'obtenir par index, donc chaque fois que vous appelez élémentaire dans votre première boucle, il faut Itérate à chaque article jusqu'à ce qu'il atteigne l'élément que vous avez demandé.


0 commentaires

12
votes

La méthode ellementat () est O (n), à moins que la classe de béton réelle que le ienumerable représente l'optimise. Cela signifie que chaque fois que vous l'appelez, il doit boucler à travers l'entièrement en-témoine de trouver l'élément à n . Sans oublier que depuis que vous avez i dans la partie de l'état de votre boucle, il boucle de gotta à travers l'ensemble dénombrable chaque fois que pour obtenir ce compter.

La deuxième façon, vous en boucle par résultat exactement une fois.


1 commentaires

Comme ils disent que c'est d'une jointure, je suppose que ce résultat () est réellement transformé en un compteur SQL (*) . Presque une amélioration cependant!



0
votes

Si je devais endommager une supposition, le résultat.Count () est non différé et frappe réellement la base de données alors que le forach n'est pas. Si vous retournez l'ordre, vous pouvez obtenir le résultat opposé. Aussi, vous pouvez simplement faire total = résultat.sum ();


0 commentaires

0
votes

Le premier peut être équivalent à: xxx

ou il pourrait même être équivalent à: xxx

ou cela pourrait même demander à obtenir résultat chaque fois qu'il appaire dans le code ci-dessus.

d'autre part, comptez () pourrait être obtenu par un accès de propriété, et ollementat () pourrait être O (1), si ceux-ci sont sauvegardés sur des structures permettant une telle optimisation, et une telle optimisation était en effet disponible (par exemple, c'est pour Liste ).


0 commentaires

0
votes

C'est tout sur la compréhension de l'exécution différée! Lorsqu'une requête est exécutée plusieurs fois, le temps de fonction augmente considérablement. LINQ peut être plus rapide, mais vous devez vraiment faire un choix en fonction de la façon dont vous allez utiliser vos résultats de requête.

Jetez un oeil à cet article http://allthingscs.blogspot.com/ 2011/03 / linq-Performance.html . Il analyse cette question très problématique.


0 commentaires