重载运算符查找性能

时间:2012-03-07 15:40:23

标签: c# performance operator-overloading

如果a和b是双倍的,有人知道是否

((dynamic)a) + ((dynamic) b) 

更快或更慢
Func<double,double,double>((x,y) => x + y)(a, b)

你能解释一下原因吗?

2 个答案:

答案 0 :(得分:4)

第一个版本总是会慢一些。用这个版本非常简单的术语编译器在编译时可以完成的所有事情现在都要在运行时完成,即。检查a和b的类型,查找它们是否支持+运算符等。它会缓存很多这样的东西,但它仍然比调用委托更多的工作。

在第二个版本中,所有这些检查都可以在编译期间完成。运行时的成本只是委托的创建和调用。

例如,请考虑以下方法:

static T Add<T>(T a, T b)
{
  return ((dynamic)a) + ((dynamic)b);
}

相反
static T Add<T>(T a, T b, Func<T, T, T> adder)
{
  return adder(a, b);
}

这是编译器从第一种方法生成的内容:

private static T Add<T>(T a, T b)
{
  if (Program.<Add>o__SiteContainer0<T>.<>p__Site1 == null)
  {
    Program.<Add>o__SiteContainer0<T>.<>p__Site1 = CallSite<Func<CallSite, object, T>>.Create(Binder.Convert(CSharpBinderFlags.None, typeof(T), typeof(Program)));
  }
  Func<CallSite, object, T> arg_98_0 = Program.<Add>o__SiteContainer0<T>.<>p__Site1.Target;
  CallSite arg_98_1 = Program.<Add>o__SiteContainer0<T>.<>p__Site1;
  if (Program.<Add>o__SiteContainer0<T>.<>p__Site2 == null)
  {
    Program.<Add>o__SiteContainer0<T>.<>p__Site2 = CallSite<Func<CallSite, object, object, object>>.Create(Binder.BinaryOperation(CSharpBinderFlags.None, ExpressionType.Add, typeof(Program), new CSharpArgumentInfo[]
    {
      CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
      CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
    }));
  }
  return arg_98_0(arg_98_1, Program.<Add>o__SiteContainer0<T>.<>p__Site2.Target(Program.<Add>o__SiteContainer0<T>.<>p__Site2, a, b));
}

我做了一些原始测量,在我的机器上,第一个版本比第二个版本慢约5倍。我不得不承认,我希望差异更大。

更新:至于证明为什么这比委托慢:鉴于生成的调用站点代码也涉及调用委托(arg_98_0),这段代码(委托的调用+ X)必须比仅使用委托慢。

答案 1 :(得分:1)

动态肯定会比第一次运行时强类型的func慢。至于为什么,我将在Ericover上向您推荐Stackoverflow的最终答案。

根据我的理解,重复的惩罚将是og拳击,复制和/或在堆上分配这些值。

C# Dynamic Keyword — Run-time penalty?