Люди бесчисленное количество раз доказывали, что yield return
медленнее, чем list
.
Пример: Является ли "доходность" медленнее, чем доходность "старой школы"?
Однако, когда я попытался выполнить тест, я получил противоположные результаты:
Results:
TestYield: Time =1.19 sec
TestList : Time =4.22 sec
Здесь список на 400% медленнее.Это происходит независимо от размера.Это не имеет смысла.
IEnumerable<int> CreateNumbers() //for yield
{
for (int i = 0; i < Size; i++) yield return i;
}
IEnumerable<int> CreateNumbers() //for list
{
var list = new List<int>();
for (int i = 0; i < Size; i++) list.Add(i);
return list;
}
Вот как я их потребляю:
foreach (var value in CreateNumbers()) sum += value;
Я использую все правильные правила тестирования, чтобы избежать противоречивых результатов, так что это не проблема.
Если вы видите код, лежащий в основе, yield return
- это мерзость конечного автомата, но она быстрее.Почему?
Редактировать: Все ответы реплицированы, что действительно Урожай быстрее, чем список.
New Results With Size set on constructor:
TestYield: Time =1.001
TestList: Time =1.403
From a 400% slower difference, down to 40% slower difference.
Тем не менее, понимание является потрясающим.Это означает, что все те программисты 1960 года и позже, которые использовали список в качестве коллекции по умолчанию, были неправы и должны были быть застрелены (уволены), потому что они не использовали лучший инструмент для ситуации (yield).
Ответы утверждали, что доходность должна быть быстрее, потому что она не материализована.
1) Я не принимаю эту логику.У выхода есть внутренняя логика, это не «теоретическая модель», а конструкция компилятора.Поэтому он автоматически материализуется на потребление.Я не принимаю аргумент, что это «не материализовалось», так как стоимость уже оплачена при использовании.
2) Если лодка может путешествовать по морю, но старуха не может, вы не можете,требовать, чтобы лодка "двигалась по суше"Как вы сделали здесь со списком.Если список требует материализации, а доходность - нет, то это не «проблема доходности», а «особенность».Доходность не должна быть оштрафована в тесте, просто потому, что он имеет больше применений.
3) Я утверждаю, что целью теста было найти «Самую быструю коллекцию» для использования / возврата возвращаемых результатов.с помощью метода, если вы знаете, что будет использоваться ENTIRE SET .
Станет ли yield новым "стандартом де-факто" для возврата аргументов списка из методов.
Edit2: если я использую чистый встроенный массив, он получает ту же производительность, что и Yield.
Test 3:
TestYield: Time =0.987
TestArray: Time =0.962
TestList: Time =1.516
int[] CreateNumbers()
{
var list = new int[Size];
for (int i = 0; i < Size; i++) list[i] = i;
return list;
}
Следовательно, yield автоматически включается в массив.Список не.