0

if a and b are double, does anyone know if

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

is faster or slower than

Func<double,double,double>((x,y) => x + y)(a, b)

And can you explain why?

edeboursetty
  • 5,669
  • 2
  • 40
  • 67
  • 1
    Where is this question coming from? The two pieces of code are completely different, and I don't see why they are being compared. – Ken Wayne VanderLinde Mar 07 '12 at 15:48
  • @Ken: the two statements have the same input and the same output, so it makes perfect sense to compare their performance. – edeboursetty Mar 07 '12 at 15:52
  • 4
    You have two horses. You wish to know which one is faster. So you show photos of the horses to strangers on the internet and ask them for an opinion? I would be inclined to *race the horses*. You've written the code both ways. Now *run the code both ways* and *see which way is faster*, and then you'll know the answer to your question, rather than relying upon guesses from strangers. – Eric Lippert Mar 07 '12 at 15:56
  • @EricLippert: I could have raced the two horses indeed, but then I would have asked the strangers on the internet why the first one was slower than the second one. And the strangers would have happily replied to me that it was obvious because the first one had only three legs. So in the end 1: I get my response very fast, 2: I get an explanation, 3: everyone who is reading this will know that a 3-legged horse is slower than his 4-legged cousin, and 4: I get to discuss horse racing with my fellow developper. – edeboursetty Mar 07 '12 at 16:22

2 Answers2

4

The first version will always be slower. In very simple terms with this version everything that the compiler can do at compile time has now to be done at runtime, ie. checking the types of a and b, finding if they support the + operator and so on. It will cache a lot of this stuff, but still it is much more work than invoking a delegate.

In the second version all those checks can be done during compilation. The cost at runtime are only the creation and invocation of the delegate.

For example, consider those methods:

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

in contrast to

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

This is what the compiler generates from the first method:

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

I've done some crude measurements and on my machine the first version is about 5 times slower than the second. I have to admit that I would have expected the difference to be larger.

Update: As for a prove why this is slower than a delegate: Given that the generated call site code also involves the invocation of a delegate (arg_98_0), this piece of code (invocation of delegate + X) must necessarily be slower than using a delegate only.

Andre Loker
  • 8,368
  • 1
  • 23
  • 36
1

dynamic will definitely be slower than the strongly typed func the first time it runs. And as to why, I will refer you to the definitive answer by Eric Lippert here on Stackoverflow.

As I understand it, the recurring penalty will be og boxing, copying and/or allocating these values on the heap.

C# Dynamic Keyword — Run-time penalty?

Community
  • 1
  • 1
Ani
  • 10,826
  • 3
  • 27
  • 46