Question

J'entends constamment à quel point la réflexion est mauvaise à utiliser.Même si j'évite généralement la réflexion et trouve rarement des situations où il est impossible de résoudre mon problème sans elle, je me demandais...

Pour ceux qui ont utilisé la réflexion dans des applications, avez-vous mesuré les performances et est-ce vraiment si mauvais ?

Était-ce utile?

La solution

C'est.Mais cela dépend de ce que vous essayez de faire.

J'utilise la réflexion pour charger dynamiquement des assemblys (plugins) et sa "pénalité" de performance n'est pas un problème, puisque l'opération est quelque chose que je fais lors du démarrage de l'application.

Cependant, si vous réfléchissez à l'intérieur d'une série de boucles imbriquées avec des appels de réflexion sur chacune, je dirais que vous devriez revoir votre code :)

Pour les opérations "quelques fois", la réflexion est parfaitement acceptable et vous ne remarquerez aucun retard ni problème.C'est un mécanisme très puissant et il est même utilisé par .NET, donc je ne vois pas pourquoi vous ne devriez pas l'essayer.

Autres conseils

Dans son discours La performance des choses du quotidien, Jeff Richter montre qu'appeler une méthode par réflexion revient à 1000 fois plus lent que de l'appeler normalement.

Le conseil de Jeff :si vous devez appeler la méthode plusieurs fois, utilisez la réflexion une fois pour la trouver, puis attribuez-la à un déléguer, puis appelez le délégué.

Les performances de réflexion dépendront de l'implémentation (les appels répétitifs doivent être mis en cache, par exemple : entity.GetType().GetProperty("PropName")).Étant donné que la plupart des réflexions que je vois au quotidien sont utilisées pour remplir des entités à partir de lecteurs de données ou d'autres structures de type référentiel, j'ai décidé de comparer les performances spécifiquement sur la réflexion lorsqu'elle est utilisée pour obtenir ou définir les propriétés d'un objet.

J'ai conçu un test que je pense juste car il met en cache tous les appels répétitifs et ne multiplie que l'appel SetValue ou GetValue réel.Tout le code source du test de performances se trouve dans bitbucket à l'adresse : https://bitbucket.org/grenade/accessortest.L’examen est le bienvenu et encouragé.

La conclusion à laquelle je suis arrivé est qu'il n'est pas pratique et n'apporte pas d'améliorations notables des performances de supprimer la réflexion dans une couche d'accès aux données qui renvoie moins de 100 000 lignes à un moment où la mise en œuvre de la réflexion est bien effectuée.

Graph of time (y) against number of entities populated(x)

Le graphique ci-dessus démontre le résultat de mon petit benchmark et montre que les mécanismes qui surpassent la réflexion ne le font sensiblement qu'après la barre des 100 000 cycles.La plupart des DAL ne renvoient que plusieurs centaines, voire milliers de lignes à la fois et à ces niveaux, la réflexion fonctionne très bien.

Si vous n’êtes pas au courant, ne vous inquiétez pas.

Mon expérience la plus pertinente a été d'écrire du code pour comparer deux entités de données du même type dans un modèle d'objet volumineux en termes de propriétés.Je l'ai fait fonctionner, je l'ai essayé, j'ai couru comme un chien, évidemment.

J'étais découragé, puis j'ai réalisé du jour au lendemain que sans changer la logique, je pouvais utiliser le même algorithme pour générer automatiquement des méthodes permettant d'effectuer la comparaison mais d'accéder statiquement aux propriétés.Il n'a pas fallu de temps pour adapter le code à cet effet et j'ai eu la possibilité d'effectuer une comparaison approfondie des entités avec un code statique qui pouvait être mis à jour d'un simple clic à chaque fois que le modèle objet changeait.

Mon point est :Depuis lors, lors de conversations avec des collègues, j'ai souligné à plusieurs reprises que leur utilisation de la réflexion pourrait consister à générer automatiquement du code à compiler plutôt que d'effectuer des opérations d'exécution, ce qui mérite souvent d'être pris en compte.

Pas massivement.Je n'ai jamais eu de problème avec cela dans le développement de postes de travail, à moins que, comme le dit Martin, vous ne l'utilisiez dans un endroit idiot.J'ai entendu dire que beaucoup de gens avaient des craintes totalement irrationnelles quant à ses performances dans le développement d'ordinateurs de bureau.

Dans le Cadre Compact (dans lequel je suis habituellement) cependant, c'est à peu près anathème et doit être évité comme la peste dans la plupart des cas.Je peux encore m'en sortir en l'utilisant rarement, mais je dois faire très attention à son application qui est beaucoup moins amusante.:(

C'est déjà assez grave de devoir s'inquiéter même de la réflexion effectuée en interne par les bibliothèques .NET pour le code critique en termes de performances.

L'exemple suivant est obsolète - vrai à l'époque (2008), mais corrigé depuis longtemps dans les versions CLR plus récentes.La réflexion en général reste cependant une chose quelque peu coûteuse !

Exemple concret :Vous ne devez jamais utiliser un membre déclaré comme « Objet » dans une instruction lock (C#) / SyncLock (VB.NET) dans du code hautes performances.Pourquoi?Parce que le CLR ne peut pas se verrouiller sur un type valeur, ce qui signifie qu'il doit effectuer une vérification du type de réflexion au moment de l'exécution pour voir si votre objet est réellement un type valeur au lieu d'un type référence.

Comme pour tout ce qui concerne la programmation, vous devez équilibrer le coût des performances avec les avantages obtenus.La réflexion est un outil précieux lorsqu’elle est utilisée avec précaution.J'ai créé une bibliothèque de mappage O/R en C# qui utilisait la réflexion pour effectuer les liaisons.Cela a fonctionné à merveille.La plupart du code de réflexion n’a été exécuté qu’une seule fois, donc toute baisse de performances était assez faible, mais les avantages étaient importants.Si j'écrivais un nouvel algorithme de tri fandangled, je n'utiliserais probablement pas la réflexion, car son échelle serait probablement médiocre.

J'apprécie de ne pas avoir répondu exactement à votre question ici.Ce que je veux dire, c'est que cela n'a pas vraiment d'importance.Utilisez la réflexion le cas échéant.Il s'agit simplement d'une autre fonctionnalité linguistique dont vous avez besoin pour apprendre comment et quand l'utiliser.

La réflexion peut avoir un impact notable sur les performances si vous l'utilisez pour créer fréquemment des objets.J'ai développé une application basée sur Bloc d'application d'interface utilisateur composite qui repose beaucoup sur la réflexion.Il y avait une dégradation notable des performances liée à la création d'objets via la réflexion.

Cependant, dans la plupart des cas, l'utilisation de la réflexion ne pose aucun problème.Si votre seul besoin est d'inspecter un assemblage, je recommanderais Mono.Cécil ce qui est très léger et rapide

La réflexion est coûteuse en raison des nombreuses vérifications que le runtime doit effectuer chaque fois que vous faites une demande pour une méthode correspondant à une liste de paramètres.Quelque part au fond, il existe du code qui parcourt toutes les méthodes d'un type, vérifie sa visibilité, vérifie le type de retour et vérifie également le type de chaque paramètre.Tout cela prend du temps.

Lorsque vous exécutez cette méthode en interne, il existe du code qui fait des choses comme vérifier que vous avez transmis une liste de paramètres compatibles avant d'exécuter la méthode cible réelle.

Si possible, il est toujours recommandé de mettre en cache le handle de méthode si l'on souhaite le réutiliser continuellement à l'avenir.Comme tous les bons conseils de programmation, il est souvent judicieux d’éviter de se répéter.Dans ce cas, il serait inutile de rechercher continuellement la méthode avec certains paramètres, puis de l'exécuter à chaque fois.

Parcourez la source et jetez un œil à ce qui se fait.

Comme pour tout, il s’agit d’évaluer la situation.Dans DotNetNuke il y a un composant assez central appelé FillObject qui utilise la réflexion pour remplir les objets des lignes de données.

C'est un scénario assez courant et il y a un article sur MSDN, Utilisation de Reflection pour lier des objets métier aux contrôles de formulaire ASP.NET qui couvre les problèmes de performances.

Performances mises à part, une chose que je n'aime pas dans l'utilisation de la réflexion dans ce scénario particulier est qu'elle tend à réduire la capacité de comprendre le code d'un coup d'œil rapide, ce qui pour moi ne semble pas en valoir la peine si l'on considère que vous perdez également la compilation. sécurité du temps par opposition aux ensembles de données fortement typés ou quelque chose comme LINQ vers SQL.

La réflexion ne ralentit pas considérablement les performances de votre application.Vous pourrez peut-être effectuer certaines choses plus rapidement en n'utilisant pas la réflexion, mais si la réflexion est le moyen le plus simple d'obtenir certaines fonctionnalités, utilisez-la.Vous pouvez toujours refactoriser votre code en dehors de Reflection si cela devient un problème de performances.

Je pense que vous constaterez que la réponse est que cela dépend.Ce n'est pas grave si vous souhaitez le mettre dans votre application de liste de tâches.C'est un gros problème si vous souhaitez le mettre dans la bibliothèque de persistance de Facebook.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top