Cette question est en partie sur les délégués et en partie sur les génériques.
donné le code simplifié: p> i lue ailleurs sur SO qui invoquant un délégué directement (avec des parenthèses) est des ordres de grandeur plus rapidement que d'appeler < Code> dynamicinvoke code>, ce qui a du sens. p> Pour l'échantillon de code ci-dessus, je me demande si je peux effectuer la vérification du type et améliorer la performance. P> Certains contextes: em> J'ai un flux d'objets qui obtiennent de nombreux gestionnaires à divers gestionnaires, et ces gestionnaires peuvent être enregistrés / non enregistrés au moment de l'exécution. Le motif ci-dessus fonctionne parfaitement à mes fins, mais je voudrais le rendre plus snappier si possible. P> une option serait de stocker action
dans le
Dictionnaire code> et enveloppez le
action
3 Réponses :
Je soupçonne fortement que l'enveloppement des appels serait beaucoup plus efficace que d'utiliser dynamicinvoke code>. Votre code serait alors:
internal sealed class TypeDispatchProcessor
{
private readonly Dictionary<Type, Action<object>> _actionByType
= new Dictionary<Type, Action<object>>();
public void RegisterProcedure<T>(Action<T> action)
{
_actionByType[typeof(T)] = item => action((T) item);
}
public void ProcessItem(object item)
{
Action<object> action;
if (_actionByType.TryGetValue(item.GetType(), out action))
{
action(item);
}
}
}
Cela peut toutefois entraîner une structure étrange et confuse.
Je doute que ce serait significativement plus confus que celui généré par un appel à Dynamicinvoke.
@Jon, merci d'avoir ajouté du poids à ma suspicion. Je vais essayer de profiler cela demain quand au bureau.
Belle solution, testée, la performance est d'env. 10 fois mieux
@Valbakhtinn, je l'ai mesuré comme approximativement 270 fois plus rapide . C'était il y a quelques années, le CLR a peut-être changé.
Alors j'ai fait des mesures à ce sujet.
1,000,000 Action calls in 47.172 ms 1,000,000 Delegate.DynamicInvoke calls in 12,035.943 ms 1,000,000 Action calls in 44.686 ms 1,000,000 Delegate.DynamicInvoke calls in 12,318.846 ms
Si vous devez étendre ceci pour emballer des invocations de membres à partir de classes sans utiliser de réflexion.MIT Vous pouvez le faire en créant une série de conseils de compilation pouvant mapper une classe et une liste de paramètres de fonction ou de type de retour. P>
En gros, vous devez créer des lambdas qui prennent des objets comme des paramètres et renvoient un objet. Utilisez ensuite une fonction générique que le compilateur voit AOT pour créer un cache de méthodes appropriées pour appeler le membre et jeter les paramètres. L'astuce consiste à créer des délégués ouverts et à les transmettre à travers une seconde Lamda pour se rendre à l'indice sous-jacent au moment de l'exécution. P>
Vous devez fournir les astuces pour chaque classe et chaque signature (mais pas toutes les méthodes ni tous les biens). P>
J'ai travaillé une classe En tests de performance, il ne s'agit pas d'où près de l'exemple ci-dessus, mais il est générique, ce qui signifie qu'il fonctionne dans les circonstances dont j'avais besoin. Performance autour de 4,5x sur la lecture d'une propriété par rapport à invoquer. P>