Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, Serginio1, Вы писали:
S>>Здравствуйте, Ikemefula, Вы писали:
I>>>Именно. x[0] инлайнится враз и стоит считай бесплатно. А x.FirstOrDefault() в сравнении с этим неимоверно дорог.
I>>>Например, когда эта операция одна из основных в экспоненциальном алгоритме, любая издержка дает конское отставание.
S>> Я уже приводил тебе на замеры производительности. Прочитай еще раз
S>>https://mattwarren.org/2016/09/29/Optimising-LINQ/
I>Это синтетический тест, который замеряет какой то очень крохотный кейс. Я точно так же напишу другой, вида while(true) { yield i++}, пройдусь по ём сотню раз от нуля до миллиона и мы увидим, что в тысячу раз хуже и по памяти и процессору обычного цикла безо всяких массиво.
I>
S>> есть простейший запрос и оптимизаторы
S>>S>>var results = items.Where(i => i % 10 == 0)
S>> .Select(i => i + 5);
S>>
S>> Итеративно 3 удава
S>> Linq 4.88
S>> Roslyn 3.87
S>> LinqOptimiser 5.03
I>Я не сильно понимаю эти результаты. Что такое удавы и какой код получил 3 удава? Самый быстрый это 3 или 5 ?
Ну посмотри статью. Там все написано и расписано.
S>> То есть твои доводы про производительность yield идут лесом.
I>Я вижу, что здесь непойми что и не ясно, зачем вообще выделять память. Зачем делать add() если можно просто вызвать соответствующую функцию?
I>Память нужно выделять в том случае, если у нас есть многочисленные повторные проходы по источнику.
В том, что нужно получать итератор. А здесь как раз идет сравнение с итератора и через прямое вычисление без итераторов.
Так или иначе идет вызов MoveNext на стороне итератора идут 10 вызовов кстати через индекс так как передан массив.
Но нужны коллекции для заиси в базу, отображения итд
I>То есть, если ты сотню раз будешь использовать источник такого вида
I>I>while(true) {
I> yield i++;
I>}
I>
I>То ты сэкономишь кучу памяти, но при этом работа с источником окажется примерно в 1000 раз медленнее.
I>И для оптимизации используется кеширование коллекции.
В реалии Отборов может быть великое множество. Памяти не хватит кэшировать.
Мало того данные имеют свойство меняться
if (_linqitem % 10 == 0)
{
var _linqitem1 = _linqitem + 5;
yield return _linqitem1;
}
3 попугая для
public int Iterative()
{
var counter = 0;
foreach (var item in items)
{
if (item % 10 == 0)
counter += item;
}
return counter;
}
и 3.8 для
IEnumerable<int> results = compiledWhereSelectQuery(items);
var counter = 0;
foreach (var result in results)
{
counter += result;
}
то есть 0.8 секунды уходит на итератор. Учитывая что реально вызывается только каждый 10.
Можно умножить на 10 итого 8 попугая
то есть в самом писсимистичном это будет 11 попугая 11/3 максимум в 4 раза.
Но когда нам нужны коллекции заполнение List оказывается значительно дороже.
То есть вычисления слева на право себя не оправдывают