OK, nous savons donc tous que la réflexion est de plus de temps moins performant que "nouvelle" une instance de classe et, dans de nombreux cas, cela suffit, en fonction des exigences de l'application. p>
question: Comment pouvons-nous créer des cours de haute performance .NET à l'aide d'une stratégie de reliure tardive (réflexion). em> fort> p> p>
J'ai une exigence existante qui exige des instances de classe être créées à l'aide de la réflexion (CreateInstance), mais la performance est essentielle. Dans ma situation, je crée des instances pour chaque message SMS entrant dans notre application. Pendant la production, cela pourrait facilement comporter plus d'un million par jour. P>
J'aimerais entendre et partager certaines idées sur la manière de créer des classes .NET sans référencer directement les classes du code, par exemple en utilisant la réflexion. Je pensais également s'il y a un moyen d'en quelque sorte cacher une usine de classe qui peut améliorer la "création" temps p>
6 Réponses :
Je ne pense pas qu'un million par jour est trop pour un simple appel de réflexion. Je crois que vous optimisez-vous, mais de toute façon, comme vous l'avez dit, créez simplement une classe d'usine à l'aide d'un seul Activator.CreateInstance Code> Appel et cache celui-ci. Les instances réelles seront créées à l'aide de l'appel de méthode
CreateInstance () Code> sur l'objet renvoyé.
public interface IClassFactory {
IClass CreateInstance();
}
public interface IClass {
// your actual class interface.
}
public class DefaultClassFactory : IClassFactory {
public IClass CreateInstance() {
return new DefaultClass(); // the implementation class
}
}
Le seul HICCUP possible ici est si l'application est multithreadie, vous pouvez avoir plusieurs appels différents en utilisant le même instance et vous retrouver avec des instances avec un état mixte. Peut-être retourner un clone de l'objet si c'est un problème?
Hein? Pourquoi? L'usine créera toujours une nouvelle instance et sa sécurité-t-elle elle-même car elle n'a pas d'état interne.
@Matt il a dit une usine statique, pas la classe elle-même d'être statique. Les usines sont faciles à faire du thread-coffre-fort.
Mon mauvais, je lis cela comme établissant l'instance sous-jacente créée par l'usine en tant que statique pour un retour facile sans créer de nouvelles instances de la classe souhaitée
1 million par jour n'est pas beaucoup; J'utiliserais simplement pensées sur la création d'objets rapidement: P>
Une implémentation de l'approche Pour un IIL Exemple, voir Dapper -dot-net et activator.createinstance code> (un test rapide à l'aide de
Activator.CreatInstance (type) code> montre que sur mon ordinateur portable, il peut créer des objets 1M à partir d'un type
code> in ~ 2s). P>
: nouveau () code> contrainte (zéro effort) li>
dynamicmethod code> et écrivez l'IL (pas dure) li>
ul>
nouvelle code> (sans avoir besoin du
: nouveau () code> contrainte externe) est affiché ici:
ObjectFactory.cs code>
. < / p>
il.emit (opcodes.newobj, ...) code> p>
@Frank: Seulement si votre constructeur n'est pas particulièrement rapide lui-même, auquel cas rien ne vous évitera. nouveau () code> via une contrainte générique entraîne une invocation de constructeur direct réelle, de sorte qu'il n'obtient pas plus vite que cela.
@jerry - mon chronomètre me dit sinon, désolé. Depuis le nouveau générique, je reçois toujours une performance légèrement pire (5 à 8 fois plus lent). Si vous avez un look avec ildasme, le code générique appelle activateur.CreateInstance
@Frank - Si le temps de construction est que B> critique, alors dynamique serait probablement une option restante.
On dirait que le code Google a besoin du numéro de révision maintenant, alors objectfactory est à code.google.com/p/protobuf-net/source/browse/trunk/protobuf- net / ...
@Chris ah, oui; Ce fichier n'existe plus dans le coffre
Certaines pensées: p>
cache l'instance à clone ou le type dans un dictionnaire Dictionnaire
Dictionnaire
Clonage plus vite que de créer une instance d'un délégué mis en cache? Je ne pense pas que ce soit, alors aurait préférable de mettre en cache le contractant de la classe? Serait-ce un délégué? Si la réflexion a été utilisée pour obtenir le type, puis créer une instance, obtiendriez-vous l'entrepreneur du type ou de l'instance. Peut être ajouté à un exemple de code. Je crois comprendre que la mise en cache de la CTOR des types d'un dictionnaire serait la plus rapide.
Comme c'est généralement le cas, Jon Skeet est votre ami ici. Voir son blog Post Faire la mouche de réflexion et explorer les délégués p>
Définir et mettre en place une interface au lieu d'utiliser la réflexion. P>
génial! L'approche de l'usine de classe semble être la voie à suivre ici.
Utilisation d'une combinaison de sur les appels suivants Utilisation de cette approche Il est de 20% plus lent que d'utiliser un nouvel opérateur natif. Aucun gros problème là-bas! P> STATS pour la création de 10 millions de 8 secondes à l'aide de l'opérateur code> neuf p> li>
10 secondes à l'aide de l'approche usine / type / cache. p> li>
ul> Voici le code d'échantillon si quelqu'un est intéressé: p> Assembly.createInstance (typenamestring) code> sur la première demande, puis cache
Tapez code> en usine. p>
Activator.createInstance (type) Code>. P>
Employee code> Objets suivants: P>
Je pense que vous pouvez améliorer cela à l'aide d'arbres d'expression. Consultez ceci pour un Exemple < / a>.
Je ne sais pas ce que vous voyez ici en termes de libellé, comment une valeur mise en cache serait-elle 20% plus lente?
En attendant C # 4.0 Je suppose :)
Comment l'aide c # 4.0 serait-elle exactement?
L'utilisation de la réflexion pour créer une instance d'un objet est triviale dans 99,9% des cas. La réflexion dans .net est extrêmement rapide - écrivez-le et revenez plus tard si c'est un problème. Garantie que ce ne sera pas.
À partir de certains calculs de dos de serviette, pour le site Web principal, je travaille avec, nous avons moyen de plus sur 100 appels Activator.createInstance par seconde, toute la journée tous les jours. Non seulement ce n'est pas notre goulot d'étranglement de la performance, ce n'est même pas sur la liste des articles mesurables à améliorer potentiellement. Et c'est juste dans le code que nous avons écrit - n'incluant pas l'utilisation dans les bibliothèques que nous référons ou le framework .NET.
@Rex m; Eh bien ... j'irais aussi loin que dans de nombreux cas, il est "assez rapide" - mais cela peut souvent être beaucoup b> plus lent que l'approche de l'IL. Qui n'a pas d'importance si ce n'est pas un goulot d'étranglement, mais si c'était ;-p
Narc, je plaisantais comme c # 4.0 introduisant le nouveau mot clé dynamique .. (Oui, je sais que ce n'est pas vraiment ce que c'est supposé être utilisé)
Cela ressemble à une prise 22 déclaration! (: P) Réflexion et haute performance! Bonne lecture cependant.
Connexes: com / questions / 6582259 / ...