2010-01-26 6 views
2

J'ai réfléchi à la possibilité d'appliquer le modèle DI sans encourir le coût des appels de méthode virtuelle (ce qui, selon les expériences que j'ai faites, peut être jusqu'à 4 fois plus lent que les appels non virtuels). La première idée que j'avais était de faire l'injection de dépendance via génériques:Injection de dépendances dans .Net sans appels de méthode virtuelle?

sealed class ComponentA<TComponentB, TComponentC> : IComponentA 
    where TComponentB : IComponentB 
    where TComponentC : IComponentC 
{ ... } 

Malheureusement, le CLR fait encore appelle la méthode via les interfaces même lorsque les mises en œuvre concrètes de TComponentB et TComponentC sont spécifiés en tant que paramètres de type générique et toutes les classes sont déclaré comme scellé. La seule façon d'obtenir que le CLR effectue des appels non virtuels consiste à remplacer toutes les classes par des structures (qui implémentent les interfaces). Utiliser struct n'a pas vraiment de sens pour DI et rend le problème ci-dessous encore plus insoluble.

Le deuxième problème avec la solution ci-dessus est qu'il ne peut pas gérer les références circulaires. Je ne peux penser à aucun moyen, que ce soit par le code C#, ou en construisant des arbres d'expression, pour gérer des références circulaires car cela impliquerait des types génériques infiniment récursifs. (.Net supporte les types génériques en se référant à lui-même, mais il ne semble pas généraliser à ce cas.) Puisque seules les structures peuvent faire contourner les interfaces par le CLR, je ne pense pas que ce problème puisse être résolu. structures pourrait provoquer un paradoxe.

Il n'y a qu'une seule autre solution à laquelle je peux penser et c'est garanti: émettre toutes les classes à partir de zéro à l'exécution, en les basant peut-être sur des classes compilées en tant que modèles. Pas vraiment une solution idéale cependant.

Quelqu'un a de meilleures idées? Edit: En ce qui concerne la plupart des commentaires, je suppose que je devrais dire que cela est classé sous "pure curiosité intellectuelle" J'ai débattu de savoir si demander cela parce que je me rends compte que je n'ai aucun cas concret dans lequel il est nécessaire. J'y pensais juste pour m'amuser et je me demandais si quelqu'un d'autre était tombé dessus avant.

+6

4 fois plus lentement? Je trouve cela difficile à croire. Je classerais cela sous "Optimisation prématurée" ... – BFree

+0

Ceci est pour un projet personnel, sans délais, donc je me laisse aller à une optimisation prématurée :) – jthg

+0

@jthg - L'optimisation prématurée peut faire plus mal que des délais. –

Répondre

2

Bien qu'une instruction callvirt prenne plus de temps, cela est généralement effectué car cela permet de vérifier le CLR null avant de passer l'appel à la méthode. Un callvirt ne devrait pas prendre beaucoup plus de temps qu'une instruction call en particulier compte tenu de la vérification null.

Avez-vous trouvé que vous pourriez améliorer considérablement les performances de votre application en créant des types (soit structs ou des classes avec des méthodes statiques) qui vous permettent de garantir que le compilateur C# émettra call instructions plutôt que callvirt instructions? La raison pour laquelle je pose la question est que je me demande si vous allez créer une base de code non supportable qui est fragile et difficile à utiliser simplement pour résoudre un problème qui peut exister ou non.

+0

Oui, l'utilisation de structures réduit les frais généraux à presque rien. Je suppose que j'ai peut-être mal interprété la cause de l'amélioration. – jthg

+0

L'utilisation de structures réduit également la pression de la mémoire, mais leur capacité à modéliser élégamment un domaine de problème est limitée. –

4

Exemple typique d'essayer de complètement sur-concevoir quelque chose à mon avis. Juste ne compromettez pas votre conception, car vous pouvez économiser quelques dizaines de millisecondes - si c'est encore le cas.

-vous sérieusement suggérez à cause des instructions callvirt, votre application finit par être si significativement plus lent que les utilisateurs (ceux que vous écrivez l'application pour) remarqueront une différence - à tous? J'en doute énormément.

3

Cette blog post explique pourquoi vous ne pouvez pas optimiser l'appel virtuel.

+0

C'est une bonne explication. Merci. – jthg

Questions connexes