私はC#でメッセージディスパッチマップを構築しています。私は測定しているパフォーマンスの違いについて好奇心が強いですが、なぜILを調べるのは明らかではありません。C#の明示的なキャストよりもジェネリック型のキャストが遅いのはなぜですか?
メッセージマップ:
delegate void MessageHandler(Message message);
AddHandler(Type t, MessageHandler handler)
{
/* add 'handler' to messageMap invocation list */
}
delegate void GenericMessageHandler<T>(T message);
AddHandler<T>(GenericMessageHandler<T> handler) where T: Message
{
AddHandler(typeof(T), e => { handler((T)e); });
}
Dictionary<Type, MessageHandler> messageMap;
Iは、次いで、例えば、WPFでのEventArgsと同様のメッセージのクラス階層を有する:
public class Message {}
public class VelocityUpdateMessage : Message
オブザーバハンドラ関数を持つクラス:
をvoid HandleVelocityUpdate(VelocityUpdateMessage message) { ... }
&ハンドラーを呼び出す2つの方法を測定しています。私はデリゲートコールをラッピングしているので、概念的な型の安全性を少し得ることができ、そこにperfの違いがあります。
アプローチ1:リスナーが呼び出されます
AddHandler(typeof(VelocityUpdateMessage),
e => { HandleVelocityUpdate((VelocityUpdateMessage)e); });
アプローチ2:リスナーは
AddHandler<VelocityUpdateMessage>(HandleVelocityUpdate);
は、両方のアプローチは、キャストと同じメソッドの呼び出しを行うMessageHandlerのデリゲートを構築呼び出しますが、呼び出すデリゲートが使用して構築アプローチ#2は、生成されたILが同一に見えても、少し遅い。ジェネリック型へのキャスト時に余分なランタイムオーバーヘッドですか?型制約ですか?ジェネリック型が解決されたら、JITtedの代理人は同じになると思います。
ありがとうございました。
どのように測定していますか?これは、これらのマイクロ最適化では非常に重要です。 –