только функция Func и методы, влияние на производительность и многое другое - PullRequest
2 голосов
/ 23 января 2012

Есть ли какие-либо последствия для производительности для реализации ссылочно-прозрачных методов как статических функций только для чтения, а не просто как методы?Лично я нахожу версии Func более читабельными, но, возможно, традиционный способ более эффективен.

Это:

static readonly Func<DateTime, DateTime> TruncateDay =
  date => date.AddHours(-date.Hour)
              .AddMinutes(-date.Minute)
              .AddSeconds(-date.Second)
              .AddMilliseconds(-date.Millisecond);

static readonly Func<DateTime, DateTime> TruncateMonth =
  date => TruncateDay(date).AddDays(1 - date.Day);

static readonly Func<DateTime, DateTime> TruncateYear =
  date => TruncateMonth(date).AddMonths(1 - date.Month);

static readonly Func<DateTime, int> QuarterSwitch =
  date => Switch(date.Month % 3, 0,
            Case(1, 3),
            Case(2, 4),
            Case(0, 5));

По сравнению с этим:

static DateTime TruncateDay (DateTime date) 
{ 
  return date.AddHours(-date.Hour)
             .AddMinutes(-date.Minute)
             .AddSeconds(-date.Second)
             .AddMilliseconds(-date.Millisecond);
}

static DateTime TruncateMonth (DateTime date)
{ 
  return TruncateDay(date).AddDays(1 - date.Day);
}

static DateTime TruncateYear (DateTime date)
{
  return TruncateMonth(date).AddMonths(1 - date.Month);
}

static int QuarterSwitch (DateTime date)
{ 
  return Switch(date.Month % 3, 0,
           Case(1, 3),
           Case(2, 4),
           Case(0, 5));
}

Как онипредставлены внутри?На что каждый компилятор переводит?

Ответы [ 4 ]

5 голосов
/ 26 января 2012

Под капотом компилятор создает 2 дополнительных члена для каждого Func метода:

  1. Статический метод, который по сути такой же, как и в традиционном подходе.
  2. Поле «кэшированный делегат» того же типа, что и ваш делегат.

Причиной для кэшированного поля делегата является то, что это требуется компилятору для анонимных методов, которые появляются в других местах кода. В этом случае компилятор не оптимизирует поле.

Класс также требует статического конструктора для инициализации этих двух полей для каждого метода.

Некоторые из влияний на производительность:

  • Существуют небольшие издержки при вызове закрытой статической функции. Эти издержки увеличиваются с увеличением размера списка аргументов.
  • Func методы никогда не могут быть встроены. Это может иметь большое значение для очень маленьких методов.
  • Метаданные для вашего класса будут примерно в 3 раза больше. Это не бесплатно, но его эффекты трудно определить количественно.

Некоторые другие недостатки использования этого:

  • Перегрузка невозможна.
  • Имена параметров не отображаются в Intellisense.
  • Он нарушает ожидания несколькими способами, включая тот факт, что методы отображаются в виде полей в списке завершения оператора.
3 голосов
/ 23 января 2012

Попробовав TruncateDay в простом цикле, я получил метод, который оказался немного более быстрым - достаточно близко, чтобы самые медленные запуски с методом были медленнее, чем самые быстрые с делегатом, но все же почти согласованно, что делегат как правило, чуть менее производительный.

Затем я попытался использовать версию, которая просто возвращает переданное ей значение. Мой план состоял в том, чтобы иметь метод, который определенно должен быть встроенным, и версия метода была примерно в 5 раз быстрее, чем версия делегата. Очевидный вывод состоит в том, что метод действительно был встроенным, а делегат - нет, хотя это, конечно, предположение.

Тем не менее, достаточно предположить, что есть по крайней мере некоторые оптимизации, которые сделаны для методов, которые не сделаны для делегатов. Не исключено, что еще может быть что-то большее.

2 голосов
/ 25 января 2012

Статические методы будут намного быстрее, если сами их тела будут дешевыми.Если тело дорогое, это не имеет значения.

JIT не может встроить содержимое делегата и должен использовать косвенный вызов.И то, и другое ужасно (для дешевых методов).

Кроме того, с точки зрения качества кода это недопустимо:

  • Больше кода
  • Для большинства людей менее читабельнопотому что они используются в традиционном стиле
  • Нет поддержки рефакторинга
  • Против обычных идиом
  • Более сложные

Я настоятельно рекомендую вам просто пойтис традиционным способом в этом случае.Если бы я был руководителем проекта, я бы не стал терпеть такой код без особой причины.

0 голосов
/ 12 июня 2012

Это помогает мне. Поход будет делать то же самое для вас.

grid.Sort.Enabled = false;
grid.Data Source = _data source_;

//Add a single object to the beginning of the grid
grid.Nodes.Insert(0, _new_object_);

//Add a single object to the beginning of the binding list
I Binding List bl = ...;
bl.Insert(0, _new_object_); 
...