перегруженный оператор поиска производительности - PullRequest
0 голосов
/ 07 марта 2012

если a и b двойные, кто-нибудь знает, если

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

быстрее или медленнее, чем

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

И можете ли вы объяснить, почему?

Ответы [ 2 ]

4 голосов
/ 07 марта 2012

Первая версия всегда будет медленнее. Проще говоря, с этой версией все, что может сделать компилятор во время компиляции, теперь должно быть выполнено во время выполнения, т.е. проверка типов 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 голос
/ 07 марта 2012

dynamic будет определенно медленнее, чем строго типизированный func при первом запуске.И что касается того, почему, я отсылаю вас к окончательному ответу Эрика Липперта здесь, на Stackoverflow.

Насколько я понимаю, повторяющимся штрафом будет og бокс, копирование и / или распределение этих значений в куче.

C # Динамическое ключевое слово - штраф за время выполнения?

...