Производительность C # с коллекциями и итераторами

#c# #.net #performance #oop #iterator

#c# #.net #Производительность #ооп #итератор

Вопрос:

Не могли бы вы, пожалуйста, объяснить, отличается ли подход, использованный в примере 1, по производительности от подхода в примере 2? Если да, то какой из них наиболее эффективен и почему.

«Производительность», о которой я говорю, связана не только со скоростью выполнения. Я также хотел бы получить некоторые пояснения об использовании различных системных ресурсов.

1.

     private IEnumerable<string> GetObjectsStrings(List<object> input)
    {
        IList<string> result = new List<string>();

        foreach (var item in input)
        {
            result.Add(item.ToString());
        }

        return resu<
    }
  

2.

     private IEnumerable<string> GetObjectsStrings(List<object> input)
    {
        foreach (var item in input)
        {
            yield return item.ToString();
        }
    }
  

Комментарии:

1. Если вы хотите повысить производительность, возможно, вам захочется использовать массив, но я полагаю, что это одно и то же. Создайте набор тестов, который умножает функции, выполняемые над одним и тем же объектом, на пару тысяч раз. Это подскажет вам, какой из них работает быстрее.

2. Гоните своих лошадей!

3. Почему бы просто не попробовать это путем измерения ?

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

5. Я просто ищу, где я просил «быстродействие». Что-то может быть более производительным, чем что-то другое, просто делая что-то «лучше», а не просто быстрее.

Ответ №1:

В сценарии 1 вы обрабатываете весь список, а затем возвращаете этот список через IEnumerable интерфейс. Независимо от того, что вызывающий объект намеревается сделать с возвращенным IEnumerable списком, весь список обрабатывается при каждом GetObjectsStrings вызове.

В сценарии 2 вы обрабатываете только столько записей из input списка, сколько требуется вызывающей стороне. Итак, вы создаете итератор.

Вот пример, где это могло бы иметь значение:

var temp = GetObjectsStrings(input).First();

Сценарий 1: Вы выполняете input полную обработку для каждого такого вызова каждый раз. Сценарий 2: Вы обрабатываете только первый элемент в input . Затем итерация завершена.

Комментарии:

1. обратите внимание, что если бы использовался LINQ Select , также обрабатывался бы только 1 элемент

Ответ №2:

Они выполняют разные функции, так что разница определенно будет.

Первый — это создание нового списка, который содержит ToString версию элементов из существующего списка, а затем возврат этого нового списка.

Второй способ заключается в переборе существующего списка и возврате ToString версии без создания каких-либо копий.

2 является наиболее эффективным (с точки зрения скорости и использования памяти), потому что не создаются новые списки или копии чего-либо.

Комментарии:

1. Итак, единственное преимущество этого подхода в том, что мне не нужно создавать объекты в моем методе для хранения копии обрабатываемых данных, верно?

2. Это не единственное преимущество, но я думаю, что реальный вопрос в том, что вы делаете? Эти две функции «разные». Выходные данные могут быть эквивалентными, но они разные.

3. Это именно то, что я пытался спросить. Я вижу, что эти две функции выдают одинаковый результат (очевидно, при одинаковых входных данных). Я хотел бы, чтобы какой-нибудь «эксперт» в этой теме объяснил мне, почему второй подход оптимизирован для памяти на низком уровне, потому что у меня нет навыков, чтобы самому найти эту информацию и правильно ее понять.