Que se passe-t-il exactement dans les coulisses d'une requête LINQ par rapport à une collection d'objets? Est-ce du sucre syntaxique ou est-ce qu'il se passe quelque chose d'autre qui en fait une question plus efficace?Performances LINQ
Répondre
C'est juste du sucre syntaxique - il n'y a pas de magie impliquée.
Vous pouvez écrire le code équivalent en "longhand", en C# ou autre, et il aurait la même performance. (Le compilateur va bien sûr produire du code efficace, donc le code qu'il produit peut être une fraction plus efficace que le code que vous écrivez vous-même, simplement parce que vous ne connaissez pas le moyen le plus performant de écrivez ce code.)
Voulez-vous dire en termes d'expression d'une requête, ou que fait la requête dans les coulisses?
Les expressions de requête sont d'abord développées en C# "normal". Par exemple:
var query = from x in source
where x.Name == "Fred"
select x.Age;
se traduit à:
var query = source.Where(x => x.Name == "Fred")
.Select(x => x.Age);
La exacte signifie cela dépend du type de source
bien sûr ... en LINQ aux objets, il implémente généralement IEnumerable<T>
et Enumerable
les méthodes d'extension entrent en jeu ... mais il pourrait s'agir d'un ensemble différent de méthodes d'extension. (LINQ to SQL utiliserait les méthodes d'extension Queryable
, par exemple.)
Maintenant, supposons que nous sont LINQ aux objets ... après l'expansion de la méthode d'extension, le code ci-dessus devient:
var query = Enumerable.Select(Enumerable.Where(source, x => x.Name == "Fred"),
x => x.Age);
Ensuite, les implémentations de Select
et Where
deviennent importantes. Laissant de côté la vérification des erreurs, ils sont quelque chose comme ceci:
public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
Func<T, bool> predicate)
{
foreach (T element in source)
{
if (predicate(element))
{
yield return element;
}
}
}
public static IEnumerable<TResult> Select<TSource, TResult>
(this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
foreach (TSource element in source)
{
yield return selector(element);
}
}
Ensuite il y a l'expansion des blocs itérateur dans des machines d'état, que je pas ici mais que j'ai un article about. Enfin, il y a la conversion des expressions lambda en méthodes supplémentaires + création d'instance de délégué appropriée (ou arbres d'expression, selon les signatures des méthodes appelées).
Donc, fondamentalement, LINQ utilise un beaucoup de fonctionnalités intelligentes de C#:
- conversions d'expression Lambda (dans les instances de délégués et d'arbres d'expression)
- Méthodes d'extension
- d'inférence de type pour les méthodes génériques
- Blocs d'itération
- Types souvent anonymes (à utiliser dans les projections)
- Souvent frappe implicite pour les variables locales
- expression de requête traduction
Cependant, les opérations individuelles sont assez simples - ils ne réalisent pas l'indexation, etc. Les joints et les regroupements sont effectués en utilisant des tables de hachage, mais les requêtes simples comme "où" sont juste linéaires. N'oubliez pas que LINQ to Objects traite généralement les données comme une séquence lisible uniquement en avant - il ne peut pas faire des choses comme une recherche binaire. Normalement, je m'attendrais à ce que les requêtes manuscrites soient légèrement plus rapides que LINQ to Objects car il y a moins de couches d'abstraction, mais elles seront moins lisibles et la différence de performance ne sera généralement pas significative.
Comme toujours pour les questions de performance: en cas de doute, mesurez!
Si vous avez besoin de meilleures performances, essayez i4o - Index for Objects. Il construit des objets en mémoire pour les grandes collections (pensez à plus de 100 000 lignes), que LINQ utilise ensuite pour accélérer les requêtes. Vous avez besoin de beaucoup de données pour faire ce travail, mais les améliorations sont impressionnantes.
- 1. Données hiérarchiques dans Linq - options et performances
- 2. Performances de Linq to Objects et meilleure implémentation
- 3. Performances LINQ2SQL avec transactions
- 4. Consommation et performances de la mémoire ObjectContext
- 5. Problèmes de performances avec ADO.Net datasets
- 6. Question sur les performances LINQ2Sql en C#
- 7. C# - Collection est suffisante ou la comobinaison de LINQ permettra d'améliorer les performances?
- 8. Techniques pour surveiller/améliorer les performances dans les requêtes LINQ to SQL
- 9. DBArtisan performances tweaks
- 10. Performances QtCreator sous Windows
- 11. Multiprocesseur et performances
- 12. list.sort performances IComparer
- 13. Ruby listbox hautes performances
- 14. Optimisation des performances, WebApplication
- 15. Variables d'application et performances?
- 16. Amélioration des performances WCF
- 17. MSXML2.XMLHTTP - performances Vista
- 18. Réglage des performances
- 19. Performances de compilation CSharpCodeProvider
- 20. AspCompat performances question
- 21. performances Mysql et Count (*)
- 22. ralentissement des performances lors de l'utilisation Unicode
- 23. Problème de performances SQL Server
- 24. Optimisation des performances de Lucene
- 25. UI Performances avec bordure personnalisée
- 26. Performances XAConnection dans Oracle (10g)
- 27. Améliorations des performances C++ 0x
- 28. Performances de l'objet distant Flex
- 29. ASP.NET 1.1 Problème de performances
- 30. Performances PHP entravées par require()
Je voulais dire ce qu'il fait dans les coulisses. Par exemple, j'ai une collection d'objets. Je peux écrire une boucle For qui itère à travers la collection entière et vérifie juste la propriété pour la valeur dont j'ai besoin dans chaque objet ou je peux utiliser LINQ. LINQ semble être plus rapide dans de nombreux cas selon ce que j'ai lu. Ma question est pourquoi est-ce plus rapide et comment fait-il les recherches? – Crios
LINQ ne sera généralement pas plus rapide que le code équivalent - bien que je pense qu'il existe d'autres projets pour fournir des recherches indexées, par exemple. Si vous pouviez donner un exemple concret où vous vous attendez à ce que LINQ soit plus rapide, ce serait utile. –