リフレクションを使用するとパフォーマンスに問題が生じると多くの人が言います。以下でそれをテストしてみましょう。
直接呼び出しと反射呼び出しのパフォーマンスの違いを検証するデモを書いてみましょう。コードは次のとおりです:
1 namespace ConsoleApplication7 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //比较直接调用和反射调用的性能差异 8 //7ms vs 365ms 9 int times = 1000000;10 var program = new Program();11 CodeTimerHelper.Initialize();12 13 CodeTimerHelper.Time("直接调用", times, () =>14 {15 program.Call();16 });17 18 var t = typeof(Program);19 var obj = Activator.CreateInstance(t);20 CodeTimerHelper.Time("反射调用", times, () =>21 {22 t.InvokeMember("Call", BindingFlags.InvokeMethod, null, obj, null);23 });24 25 Console.ReadKey();26 }27 28 /// <summary>29 /// 测试方法30 /// </summary>31 public void Call()32 {33 }34 35 }36 }
テスト結果:
100万回の呼び出しから。結果は、多くの人が言っているように、この 2 つのパフォーマンスには桁違いの違いがあることを示しています。
なぜリフレクションでパフォーマンスの損失があるのですか
1. リフレクションはアセンブリとメタデータに基づいて行われます。リフレクションを使用する場合、メタデータは文字列に基づいて検索されるため、この一連の操作はパフォーマンスに影響します。
2. 大量のボックス化とボックス化解除もパフォーマンスに影響します。ターゲットの型が分からず、メソッドに渡されるパラメータは通常オブジェクト型であるため、ボックス化とボックス化解除が大量に発生します。
リフレクション パフォーマンス最適化ソリューション
ここでは、Lao Zhao によって公開されている System.Linq.Expressions.Expression
1 //3,基于表达式树2 var methodInfo = t.GetMethod("Call");3 var executor = new DynamicMethodExecutor(methodInfo);4 CodeTimerHelper.Time("Dynamic executor", times, () =>5 {6 executor.Execute(obj, null);7 });
linq の式ツリーを使用して Delegate を生成する方法に加えて、CodeDom などのコードを生成して動的にコンパイルする方法や、Emit を使用してコードを生成する方法もあります。 Reflection のパフォーマンスを向上させるには IL を直接記述する必要がありますが、比較的に上記の方法が最も簡単です。
これでリフレクション全体のまとめは完了です!
参考記事
C#基礎知識復習シリーズ15:リフレクション
2.リフレクションはリフレクション、リフレクションでできること
以上が直接呼び出しと反射呼び出しの例のチュートリアルの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。