C# Génériques Ont un Avantage de Performance?
J'ai un certain nombre de classes de données représentant les différentes entités.
Ce qui est mieux: l'écriture d'une classe générique (par exemple, pour imprimer ou de sortie XML) à l'aide de médicaments génériques et des interfaces, ou la rédaction d'une catégorie distincte pour traiter chaque classe de données?
Est-il un avantage en termes de performance ou de tout autre avantage (autre qu'il m'épargnant le temps de l'écriture des classes séparées)?
Vous devez vous connecter pour publier un commentaire.
Il y a un accroissement significatif des performances à l'aide de médicaments génériques -- vous boxing et unboxing. En comparaison avec le développement de vos propres classes, c'est un tirage au sort (avec un côté de la pièce pèse plus que l'autre). Rouler vos propres uniquement si vous pensez que vous pouvez sortir-effectuer les auteurs du cadre.
Non seulement oui, mais DIABLE, OUI. Je ne crois pas quelle est la taille d'une différence qu'ils pouvaient faire. Nous avons fait des tests dans VistaDB après une réécriture d'un petit pourcentage de la base de code utilisé ArrayLists et tables de hachage sur les génériques. 250% ou plus a été l'amélioration de la vitesse.
Lire mon blog à propos de l'essai nous ne sur les médicaments génériques vs faible type de collections. Les résultats ont soufflé notre esprit.
J'ai commencé la réécriture de beaucoup de vieux code qui a utilisé l'faiblement typé collections en fortement typé ceux. Un de mes plus grands familiariser avec l'ADO.NET l'interface, c'est qu'ils ne sont pas exposer plus fortement typé façons de placer des données dans et hors. Le temps d'incantation d'un objet et à l'arrière est une tuerie dans un volume élevé de demandes.
Un autre effet secondaire de fortement de frappe, c'est que souvent, vous trouverez faiblement typé de référence des problèmes dans votre code. Nous avons constaté que, grâce à la mise en œuvre de structures, dans certains cas, pour éviter de mettre de la pression sur le GC, nous avons pu accélérer le rythme de notre code. Combinez cela avec fortement tapant votre meilleure augmentation de la vitesse.
Parfois, vous devez utiliser faiblement typé interfaces au sein de la dot net runtime. Chaque fois que possible, bien que de chercher les moyens de rester fortement typé. Il n'a vraiment faire une énorme différence dans la performance pour les non trivial applications.
Génériques en C# sont vraiment des types génériques de la CLR point de vue. Il ne devrait pas y avoir de différence fondamentale entre la performance d'une classe générique et spécifique de la classe qui fait exactement la même chose. Ceci est différent de Java Génériques, qui sont plus d'un système automatisé de type cast, si nécessaire, ou les modèles C++ qui s'élargissent au moment de la compilation.
Voici un bon livre, un peu vieille, ce qui explique la conception de base:
"La conception et la mise en Œuvre de Génériques pour la
.NET Common Language Runtime".
Si vous avez la main-classes d'écriture pour des tâches spécifiques, les chances sont que vous pouvez optimiser certains aspects où vous auriez besoin de plus d'un détour à travers une interface d'un type générique.
En résumé, il y a peut être un gain de performances, mais je vous recommande la solution générique d'abord, puis optimiser si nécessaire. Cela est particulièrement vrai si vous vous attendez à instancier le générique avec de nombreux types différents.
J'ai fait de la simple analyse comparative sur la liste de tableaux de vs Générique Listes pour une autre question: Les génériques vs. Tableau liste, votre kilométrage peut varier, mais la Liste Générique était de 4,7 fois plus rapide que la liste de tableaux.
Donc oui, boxing /unboxing sont essentiels si vous faites beaucoup d'opérations. Si vous faites de la simple CRUD des trucs, je ne serais pas s'inquiéter à ce sujet.
Les génériques sont un de la manière de paramétrer le code et d'éviter les répétitions. En regardant votre programme de description et de votre pensée de l'écriture d'une catégorie distincte pour chacun et chaque objet de données, je pencherais pour les génériques. Ayant une classe unique de prendre soin de nombreux objets de données, au lieu de plusieurs classes qui font la même chose, augmente vos performances. Et bien sûr vos performances, mesurées dans la capacité de changer votre code, est généralement plus important que les performances de l'ordinateur. 🙂
Selon Microsoft, les Génériques sont plus rapides que le casting (boxing/unboxing primitives) qui est vrai.
Ils prétendent aussi les génériques de fournir de meilleures performances que la conversion entre les types de référence, qui semble être faux, (on ne peut tout à fait le prouver).
Tony Northrup - co-auteur de SCTM 70-536: Développement d'Application de la Fondation - unis dans le même livre le suivant:
Je n'ai pas été en mesure de reproduire ces avantages de performance avec les génériques par rapport à la conversion entre les types de référence - je dirais donc que le gain de performance est "censé" plus "significatif".
List<string>
) avec un équivalent générique (commeStringCollection
) et cette comparaison ne prend pas en dire beaucoup sur la performance des génériques en lui-même, mais plutôt compare les performances de ces deux implémentations. Le Casting est tout à fait une opération coûteuse, de sorte que vous auriez normalement voir une amélioration des performances lors de l'utilisation d'un type générique (qui vous permet d'économiser de casting) sur un non-type générique et d'avoir à jeter constamment.si vous comparez une liste générique (par exemple) à une liste spécifique pour exactement le type que vous utilisez, alors la différence est minime, les résultats de l'compilateur JIT sont presque les mêmes.
si vous comparez une liste générique d'une liste d'objets, puis il y a des avantages importants pour la liste générique - aucune boxing/unboxing pour les types de valeur et pas de vérifications de type pour les types référence.
également le générique de la collection de classes dans le .net de la bibliothèque ont été largement optimisé et il est rare de faire mieux vous-même.
Les génériques sont plus rapides!
J'ai aussi découvert que Tony Northrup a écrit des choses fausses sur les performances de génériques et non génériques dans son livre.
J'ai écrit à ce sujet sur mon blog:
http://andriybuday.blogspot.com/2010/01/generics-performance-vs-non-generics.html
Est ici très bien l'article, où l'auteur compare les performances des génériques et non génériques:
nayyeri.net/use-generics-to-improve-performance
Si vous songez à une classe générique des appels de méthodes sur une interface pour faire son travail, qui sera plus lente que les classes spécifiques à l'aide de types connus, parce que l'appel d'une méthode de l'interface est plus lent qu'un (non virtuelle) d'appel de fonction.
Bien sûr, sauf si le code est la partie lente de la performance des processus critique, vous devez vous concentrer de clarté.
Dans le cas du générique de collections vs boxe et al, avec des collections plus anciennes comme ArrayList, les génériques sont une performance de gagner. Mais dans la grande majorité des cas, ce n'est pas l'avantage le plus important de médicaments génériques. Je pense qu'il y a deux choses qui sont de beaucoup plus d'avantages:
Génériques de promouvoir la sécurité de type, en forçant un plus homogène de la collection. Imaginer tomber sur une chaîne lorsque vous vous attendez à un int. Ouch.
Générique collections sont également plus d'autonomie à la documentation. Considérons les deux collections ci-dessous:
La lecture de la première ligne vous pourriez penser listOfNames est une liste de chaînes. Faux! Il est en fait de stocker des objets de type NameType. Le deuxième exemple non seulement impose que le type doit être NameType (ou un descendant), mais le code est plus lisible. Je sais tout de suite que j'ai besoin d'aller trouver TypeName et d'apprendre comment l'utiliser simplement en regardant le code.
J'ai vu beaucoup de ces "x mieux que y" questions sur StackOverflow. La question ici est très juste, et il s'avère que les génériques sont une victoire de la manière que vous la peau du chat. Mais à la fin de la journée, le point est de fournir à l'utilisateur avec quelque chose d'utile. Assurez-vous que votre application doit être en mesure d'effectuer, mais il a aussi besoin de ne pas planter, et vous devez être en mesure de réagir rapidement à des bugs et demandes de fonctionnalités. Je pense que vous pouvez voir comment ces deux derniers points en lien avec le type de la sécurité et de la lisibilité du code du générique de collections. Si c'était le cas contraire, si ArrayList surperformé Liste<>, je serais probablement prendre encore la Liste des<> mise en œuvre, à moins que la différence de performances est importante.
Autant que la performance passe (en général), je serais prêt à parier que vous trouverez la majorité de vos goulots d'étranglement des performances dans ces domaines au cours de votre carrière:
Aucune de ces sont fixés avec une seule ligne de solutions. Nous, en tant que programmeurs, des ingénieurs et des geeks veux savoir tous les peu de fraîcheur performance astuces. Mais il est important pour nous de garder nos yeux sur la balle. Je crois en se concentrant sur une bonne conception et les pratiques de programmation dans les quatre domaines que j'ai mentionnés ci-dessus vont plus loin que causer bien plus que de s'inquiéter de petits gains de performance.
Voir Rico Mariani sur son Blog MSDN trop:
http://blogs.msdn.com/ricom/archive/2005/08/26/456879.aspx
L'article est un peu vieux, mais en donne les détails.
Non seulement pouvez-vous vous faire disparaître de la boxe mais le générique implémentations sont un peu plus rapide que les non générique homologues avec les types de référence en raison d'un changement dans l'implémentation sous-jacente.
Les originaux ont été conçus avec une extension particulière de modèle à l'esprit. Ce modèle n'a jamais été vraiment utilisé (et aurait été une mauvaise idée de toute façon), mais la décision de conception forcé d'un couple de méthodes pour être virtuel et donc uninlineable (basé sur l'actuel et le passé JIT optimisations à cet égard).
Cette décision a été corrigé dans la nouvelle version du les classes, mais ne peut pas être modifié dans les anciennes, sans qu'il soit un potentiel binaire modification de rupture.
En outre itération via un foreach sur une Liste<> (plutôt que de IList<>) est plus rapide grâce à la liste de tableaux de l'agent Recenseur nécessitant une allocation de tas. Il est vrai que cela a conduit à une bug obscure