Проблемы / возможности / рекомендации по производительности лямбда-выражения C #

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

public IEnumerable GetItems(int point)
{
    return this.items.Where(i => i.IsApplicableFor(point));
}

, то здесь происходит некоторый подъем переменной, связанный с параметром point , потому что это свободная переменная с точки зрения лямбда. Если бы я вызвал этот метод миллион раз, было бы лучше оставить его как есть или изменить его каким-либо образом, чтобы улучшить его производительность?

Какие варианты у меня есть и какие реально осуществимы? Насколько я понимаю, я должен избавиться от бесплатные переменные, поэтому компилятору не нужно будет создавать закрывающий класс и создавать его экземпляр при каждом вызове этого метода. Это создание экземпляра обычно занимает значительное время по сравнению с версиями без закрытия.

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

Альтернативный метод

и пример кода консольного приложения

Я также написал другую версию того же метода, который не требует подъема переменных (по крайней мере, я думаю, что нет, но вы, ребята, поймите это, дайте мне знать, если это так):

public IEnumerable GetItems(int point)
{
    Func> buildPredicate = p => i => i.IsApplicableFor(p);
    return this.items.Where(buildPredicate(point));
}

Посмотрите Gist здесь .Просто создайте консольное приложение и скопируйте весь код в файл Program.cs внутри блока namespace . Вы увидите, что второй пример намного медленнее, даже если он не использует свободные переменные.

Противоречивый пример

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

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

Изменить

Ваши предложения, похоже, не работают

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

private int Point { get; set; }
private bool IsItemValid(Item item)
{
    return item.IsApplicableFor(this.Point);
}

public IEnumerable GetItems(int point)
{
    this.Point = point;
    return this.items.Where(this.IsItemValid);
}

Интересно, что это работает так же медленно, как и медленная версия. Я не знаю почему, но, похоже, он не делает ничего, кроме быстрого. Он повторно использует ту же функциональность, потому что эти дополнительные члены являются частью одного и того же экземпляра объекта. В любом случае. Я очень запутался !

Я обновил источник Gist этим последним дополнением, так что вы можете проверить это сами.

28
задан Community 23 May 2017 в 12:01
поделиться