Many people say that the use of reflection will have a performance problem, it will be more than the direct call how much slower, the following test.
Call vs Reflection Call directly
Here's a demo to verify the performance difference between the direct call and the reflection call, the code is as follows:
1 namespace ConsoleApplication7 2 {3 class program 4 {5 static void Main (string[] args) 6 {7 //Comparison Direct Performance differences for call and reflection calls 8 //7ms vs 365ms 9 int times = 1000000;10 var program = new program (); Codetimerhelper.ini Tialize (); codetimerhelper.time ("direct call", Times, () =>14 {program . Call (); + ); var t = typeof (program), var obj = activator.createinstance (t); Codetimerhelper.time ("Reflection invocation", Times, () =>21 { t.invokemember ("Call", BindingFlags.InvokeMethod, NULL , obj, null); Console.readkey ();}27//<summary>29/// test method </summary>31 public Void Call () + }34 }36}
Test results:
Judging from the results of the 1 million calls, it is true, as many people say, that there is an order of magnitude difference in performance.
Why reflection has a loss of performance
Given the loss of reflection performance, where is the specific loss?
1, reflection is based on assemblies and metadata, when using reflection, the metadata is searched, and the metadata is string-based and cannot be precompiled, so this series of operations has an impact on performance.
2, a large number of packing and unpacking also has an impact on performance. Because we are unknown to the target type, and the arguments passed to the method are usually of type object, there is a lot of boxing and unpacking.
Reflective performance Optimization Scheme
We already know that the use of reflection has a performance problem, but in some scenarios we have to use reflection technology, so we should try to optimize the reflection performance.
This refers to the old Zhao public system.linq.expressions.expression<tdelegate> expression tree class, and the direct call to compare, the code is as follows:
1//3, based on expression tree 2 var methodInfo = T.getmethod ("Call"), 3 var executor = new Dynamicmethodexecutor (methodInfo); 4 codetimerhelp Er. Time ("Dynamic executor", Times, () =>5 {6 executor. Execute (obj, null); 7});
Test results:
Wow, the same 1 million calls, using the Dynamicmethodexecutor call, are similar to the performance of a direct call.
Enclosed code with Dynamicmethodexecutor:
1//<summary> 2//3//</summary> 4 public class Dynamicmethodexecutor 5 {6 Private Func<object , object[], object> m_execute; 7 8 public Dynamicmethodexecutor (MethodInfo MethodInfo) 9 {Ten This.m_execute = this. Getexecutedelegate (methodInfo);}12 public Object Execute (object instance, object[] parameters) 14 {15 Return This.m_execute (instance, parameters);}17-Func<object, object[], object> getexecute Delegate (MethodInfo MethodInfo) {//Parameters to Execute21 parameterexpression instanceparameter = Expression.parameter (typeof (Object), "instance"); ParameterExpression Parametersparameter = Expression.parame ter (typeof (object[]), "parameters");/build parameter List25 list<expression> parameterexpres sions = new list<expression> (); parameterinfo[] Paraminfos = Methodinfo.getparameters (); t i = 0; I< Paraminfos.length; i++)//(Ti) parameters[i]30 binaryexpression valueobj = Expression.arrayindex (parame Tersparameter, Expression.constant (i)); Unaryexpression valuecast = Expression.convert (Valueobj, paramInfos[ I]. ParameterType) Parameterexpressions.add (valuecast);}34//non-instance for static met Hod, or ((tinstance) instance) the Expression Instancecast = methodinfo.isstatic? Null:Expression.Convert (Instanceparameter, methodinfo.reflectedtype); PNS//Static Invoke or ((tinstance) Insta NCE). Method39 methodcallexpression Methodcall = Expression.call (Instancecast, MethodInfo, parameterexpressions); 40 41 ((tinstance) instance). Method ((T0) parameters[0], (T1) parameters[1], ...) if (Methodcall.type = = typeof (void)) (Expression<action<object, object[]>> Lambda = Expression.lambda<action<object, object[]>> (MEthodcall, Instanceparameter, parametersparameter); Action<object, object[]> execute = lambda. Compile (); Return (instance, parameters) =>47 {$ execute (instance, parameter s); return null;50};51}52 else53 {unaryexpression c Astmethodcall = Expression.convert (Methodcall, typeof (Object)), Expression<func<object, object[], Obje Ct>> lambda = expression.lambda<func<object, object[], object>> (Castmethodcall, InstanceParameter, Parametersparameter); return lambda. Compile (); 57}58}
In addition to using the expression Tree of LINQ to generate delegate methods, there are, for example, CodeDom generating code and dynamically compiling, or using emit to write IL directly to improve the performance of the reflection, but relatively speaking, the above method is the simplest.
At this point, the entire reflection of the summary is complete!
Reference articles
A direct call to a method that reflects a call to ... Lambda expression invocation
C # Basics Carding Series 15: Reflection
Second, what is reflection, reflection can do something