为什么动态绑定不会更快?

时间:2015-09-08 05:38:42

标签: c# performance reflection

请考虑以下代码:

delegate string StringToString(string s);

MethodInfo trimMethod = typeof(string).GetMethod("Trim", new Type[0]);
var trim = (StringToString)Delegate.CreateDelegate
           (typeof(StringToString), trimMethod);
for (int i = 0; i < 1000000; i++)
     trim("test");

上面的代码动态调用字符串的Trim方法一百万次而没有显着的开销。现在,如果我们运行以下代码:

for (int i = 0; i < 1000000; i++)
     "test".Trim();

它比第一个更快。第一个必须更快,因为昂贵的动态绑定只发生一次。

我的问题是:为什么第二个比第一个跑得快?

1 个答案:

答案 0 :(得分:1)

让我们来看看ILCode

第一个使用委托,显示了许多指令来制作你的修剪,循环在我眼中可怕......

 <form name="file_upload" id="file_upload" method="post" action="upload_file.php" target="frame1" enctype="multipart/form-data" >
   <input type="file" id="file" name="file[]" multiple onchange="this.form.submit(); display_block();" /> 
 </form>

然后是另一个。

ldtoken    [mscorlib]System.String
  IL_0025:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_002a:  ldstr      "Trim"
  IL_002f:  ldc.i4.0
  IL_0030:  newarr     [mscorlib]System.Type
  IL_0035:  call       instance class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string,
                                                                                                              class [mscorlib]System.Type[])
  IL_003a:  stloc.1
  IL_003b:  ldtoken    ConsoleApplication1.Program/StringToString
  IL_0040:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_0045:  ldloc.1
  IL_0046:  call       class [mscorlib]System.Delegate [mscorlib]System.Delegate::CreateDelegate(class [mscorlib]System.Type,
                                                                                                 class [mscorlib]System.Reflection.MethodInfo)
  IL_004b:  castclass  ConsoleApplication1.Program/StringToString
  IL_0050:  stloc.2
  IL_0051:  ldc.i4.0
  IL_0052:  stloc.0
  IL_0053:  br.s       IL_0065
  IL_0055:  ldloc.2                // start of loop
  IL_0056:  ldstr      "test"
  IL_005b:  callvirt   instance string ConsoleApplication1.Program/StringToString::Invoke(string)
  IL_0060:  pop
  IL_0061:  ldloc.0
  IL_0062:  ldc.i4.1
  IL_0063:  add
  IL_0064:  stloc.0
  IL_0065:  ldloc.0
  IL_0066:  ldc.i4     0xf4240
  IL_006b:  clt
  IL_006d:  stloc.3
  IL_006e:  ldloc.3
  IL_006f:  brtrue.s   IL_0055   // iterates to next trim here
执行简单任务的大量指令是第一个更慢的原因。例如,对循环中的函数进行四次调用使得它比只有一次调用的第二次调用慢。不同基准测试的原因很可能是您的测试环境,其他进程同时进行。