为什么动态绑定不更快?



考虑以下代码:

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");

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

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

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

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

让我们看一下ILCode

第一个使用委托,显示了很多指令,使你的修剪,循环在我看来是可怕的…

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

然后是另一个

 IL_0001:  ldc.i4.0
  IL_0002:  stloc.0
  IL_0003:  br.s       IL_0014
  IL_0005:  ldstr      "test"     // loop start
  IL_000a:  callvirt   instance string [mscorlib]System.String::Trim()
  IL_000f:  pop
  IL_0010:  ldloc.0
  IL_0011:  ldc.i4.1
  IL_0012:  add
  IL_0013:  stloc.0
  IL_0014:  ldloc.0
  IL_0015:  ldc.i4     0xf4240
  IL_001a:  clt
  IL_001c:  stloc.3
  IL_001d:  ldloc.3
  IL_001e:  brtrue.s   IL_0005   // iterate

做简单任务的大量指令是第一个较慢的原因。例如,在循环中有四个函数调用,使得它比第二个只有一个调用的函数要慢。不同基准测试的原因很可能是您的测试环境中同时有其他进程在运行。

相关内容

  • 没有找到相关文章

最新更新