Информация об изменениях

Сообщение Re[39]: Есть ли подобие LINQ на других языках/платформах? от 23.04.2021 11:27

Изменено 23.04.2021 11:38 Serginio1

Re[39]: Есть ли подобие LINQ на других языках/платформах?
Здравствуйте, 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 оказывается значительно дороже.
То есть вычисления слева на право себя не оправдывают
Re[39]: Есть ли подобие LINQ на других языках/платформах?
Здравствуйте, 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 оказывается значительно дороже.
То есть вычисления слева на право себя не оправдывают