上次在MSDN网站看到一个比较动态调用代码的文章,用到的例子似乎比较复杂,为计算一个复杂多项式子而将其中部分割开,动态形成代码段来被循环调用。详细看.NET下几种动态生成代码方式比较。今天看到微软C#团队的Eric Gunnerson写的另外一篇关于动态调用代码性能的比较文章,为了说明结果和计算的准确性,减少由于函数复杂而受编译优化的影响,他使用了一个极为简单的例子:
输入一个参数,然后返回这个参数加一,这么简单的函数,优化和没有优化的代码应该不会有差别的了。

再比较动态调用代码publicclassProcessor
再比较动态调用代码
{
再比较动态调用代码
publicintProcess(intvalue)
再比较动态调用代码
{
再比较动态调用代码
returnvalue+1;
再比较动态调用代码}

再比较动态调用代码}

再比较动态调用代码
再比较动态调用代码


而对比方面,除了上次那几种外,还加了代理方式调用来进行比较。
1. 直接调用

再比较动态调用代码intvalue=processor.Process(i);

2. 用反射机制,Type.InvokeMember()调用。

再比较动态调用代码Typet=typeof(Processor);
再比较动态调用代码
intvalue=
再比较动态调用代码(
int)t.InvokeMember(
再比较动态调用代码
"Process",
再比较动态调用代码BindingFlags.Instance
|BindingFlags.Public|
再比较动态调用代码BindingFlags.InvokeMethod,
再比较动态调用代码
null,processor,newobject[]{i});
再比较动态调用代码
再比较动态调用代码

3. 通过一个接口

再比较动态调用代码publicinterfaceIProcessor
再比较动态调用代码
{
再比较动态调用代码
intProcess(intvalue);
再比较动态调用代码}

再比较动态调用代码
再比较动态调用代码

4. 通过一个委托Delegate

再比较动态调用代码publicdelegateintProcessCaller(intvalue);
再比较动态调用代码ProcessCallerprocessCaller
=newProcessCaller(processor.Process);
再比较动态调用代码
intvalue=processCaller(i);
再比较动态调用代码
再比较动态调用代码

5. 也通过反射机制建立委托再动态调用

再比较动态调用代码TypedelegateType=CreateCustomDelegate(methodInfo);
再比较动态调用代码Delegatep
=Delegate.CreateDelegate(delegateType,
再比较动态调用代码process,
"Process");
再比较动态调用代码
intvalue=(int)p.DynamicInvoke(newobject[]{i});
再比较动态调用代码
再比较动态调用代码

6. 元编程方式

对于2和5由于使用反射机制,不可避免需要建立中间的临时对象去传递参数,将参数和返回值装箱等操作,因此花费了大量的机器时间。

下面是运行的某次结果(循环100000次):
再比较动态调用代码



结论:
1.直接调用速度最快是肯定的。
2.接口调用比元编程速度快,而元编程又比委托方式快,但微软相信Whidbey会极大优化委托调用方式,从而使它接近接口调用的水平。
3.直接用Type的反射机制是速度最慢的,比用反射机制建立委托来动态调用还慢。
4.直接使用委托不够灵活,有时候需要用反射机制建立委托来调用,但会减低性能,希望Whidbey优化了委托的性能后这种情况可以改善,灵活是需要牺牲性能的。

相关代码

相关文章:

  • 2021-05-28
  • 2021-06-07
  • 2021-05-26
  • 2021-04-19
  • 2021-08-09
  • 2021-10-31
  • 2021-11-07
猜你喜欢
  • 2021-05-19
  • 2021-09-23
  • 2021-06-23
  • 2022-12-23
  • 2021-08-19
相关资源
相似解决方案