#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. Если вы хотите повысить производительность, возможно, вам захочется использовать массив, но я полагаю, что это одно и то же. Создайте набор тестов, который умножает функции, выполняемые над одним и тем же объектом, на пару тысяч раз. Это подскажет вам, какой из них работает быстрее.
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. Это именно то, что я пытался спросить. Я вижу, что эти две функции выдают одинаковый результат (очевидно, при одинаковых входных данных). Я хотел бы, чтобы какой-нибудь «эксперт» в этой теме объяснил мне, почему второй подход оптимизирован для памяти на низком уровне, потому что у меня нет навыков, чтобы самому найти эту информацию и правильно ее понять.