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

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

Изменено 24.04.2021 18:05 Serginio1

Re[39]: Есть ли подобие LINQ на других языках/платформах?
Здравствуйте, Ikemefula, Вы писали:


I>То есть, если ты сотню раз будешь использовать источник такого вида

I>
I>while(true) {
I>  yield i++;
I>}
I>

I>То ты сэкономишь кучу памяти, но при этом работа с источником окажется примерно в 1000 раз медленнее.
I>И для оптимизации используется кеширование коллекции.

Специально сделал тест
 class Program
    {
        static long InlineCalk()
        {
            long result = 0;
            for (int i = 0; i < int.MaxValue/2; i++)
                result += i;

            return result;

        }

        static IEnumerable<int> GetEnumerable()
        {
            for (int i = 0; i < int.MaxValue/2; i++)
                yield return i;
        }

        static long YieldCalk()
        {
            long result = 0;
            foreach (int i in GetEnumerable())
                result += i;

            return result;

        }
        static void Main(string[] args)
        {
            var r = DateTime.Now;

            var result=InlineCalk();
            var res = (DateTime.Now - r).TotalMilliseconds;
            Console.WriteLine(res);
            Console.WriteLine(result);
            r = DateTime.Now;
            result=YieldCalk();
            var res2 = (DateTime.Now - r).TotalMilliseconds;
            Console.WriteLine(result);
            Console.WriteLine(res2);
            Console.WriteLine($"отношение yield к inline {res2 / res}");
            Console.ReadLine();
        }
    }


727,6487
576460750692810753
576460750692810753
6389,199
отношение yield к inline 8,780609379223794



То есть ты ошибся как минимум раз в 100! Ну какая хрен разница подумаешь! Главное медленнее. Но цифрами бросаться все же не стоит.
И это на result += i; Если будут функции с поиском в хэштаблице и ли функции работы со строками,
а учитывая, что в реалии нужно обращаться к данным, которые могут находиться вне кэша памяти, то это отношение будет стремиться к 1!!
То есть ни о каких 1000 и близко нет, но вот если тебе понадобится коллекция то ты на памяти больше потеряешь.
А что мне кэшировать если
1. Данные меняются
2. Мне нужно один раз получить такой итератор с такими условиями.

Кстати в .Net появился ref return

 public class MyIterator
    {
        int Result = 0;
        int state = 0;

       public ref int ReturnResult()
        {
            return ref Result;
        }
       public bool MoveNext()
        {
 
                switch (this.state)
                {
                    case 0:
                    Result = 0;
                    state = 1;
                    return true;
                    
                    case 1:
                    Result++;
                    if (Result == int.MaxValue / 2)
                    {
                        state = 3;
                        return false;
                    }
                    return true;

                       default:
                        return false;
                }


        }

    }


И получать Current по ссылке
 static long RefResult()
        {
            long result = 0;
            var iter = new MyIterator();
            ref int res = ref iter.ReturnResult();

            while (iter.MoveNext())
                result += res;
            return result;
        }

и вызов
r = DateTime.Now;
            result = RefResult();
            var res3 = (DateTime.Now - r).TotalMilliseconds;
            Console.WriteLine(result);
            Console.WriteLine(res3);
            Console.WriteLine($"отношение RefResult к inline {res3 / res}");


То получим
576460750692810753
3235,4582
отношение RefResult к inline 4,327135105321729

То есть ошибся всего в 250 раз!!
Ну в MS считают, что это не принципиально

Но к сожалению такая конструкция

static IEnumerable<int> GetEnumerable2()
        {
            var iter = new MyIterator();
            ref int res = ref iter.ReturnResult();

            while (iter.MoveNext())
                yield return res;
        }


Ругается на ref int res = ref iter.ReturnResult();
Итераторы не могут иметь переменные по ссылке

Но если заменить MoveNext
 public bool MoveNext2(ref int result)
        {

            switch (this.state)
            {
                case 0:
                    Result = 0;
                    state = 1;
                    return true;

                case 1:
                    Result++;
                    if (Result == int.MaxValue / 2)
                    {
                        state = 3;
                        return false;
                    }
                    result = Result;
                    return true;

                default:
                    return false;
            }


        }


И вызов
 static long RefResult2()
        {
            long result = 0;
            var iter = new MyIterator();
            int res = 0;
            while (iter.MoveNext2(ref res))
                result += res;
            return result;

        }


То получим
576460750692810753
3420,4316
отношение RefResult к inline 4,805504333751022

Ну не нужно это MS
Re[39]: Есть ли подобие LINQ на других языках/платформах?
Здравствуйте, Ikemefula, Вы писали:


I>То есть, если ты сотню раз будешь использовать источник такого вида

I>
I>while(true) {
I>  yield i++;
I>}
I>

I>То ты сэкономишь кучу памяти, но при этом работа с источником окажется примерно в 1000 раз медленнее.
I>И для оптимизации используется кеширование коллекции.

Специально сделал тест
 class Program
    {
        static long InlineCalk()
        {
            long result = 0;
            for (int i = 0; i < int.MaxValue/2; i++)
                result += i;

            return result;

        }

        static IEnumerable<int> GetEnumerable()
        {
            for (int i = 0; i < int.MaxValue/2; i++)
                yield return i;
        }

        static long YieldCalk()
        {
            long result = 0;
            foreach (int i in GetEnumerable())
                result += i;

            return result;

        }
        static void Main(string[] args)
        {
            var r = DateTime.Now;

            var result=InlineCalk();
            var res = (DateTime.Now - r).TotalMilliseconds;
            Console.WriteLine(res);
            Console.WriteLine(result);
            r = DateTime.Now;
            result=YieldCalk();
            var res2 = (DateTime.Now - r).TotalMilliseconds;
            Console.WriteLine(result);
            Console.WriteLine(res2);
            Console.WriteLine($"отношение yield к inline {res2 / res}");
            Console.ReadLine();
        }
    }


727,6487
576460750692810753
576460750692810753
6389,199
отношение yield к inline 8,780609379223794



То есть ты ошибся как минимум раз в 100! Ну какая хрен разница подумаешь! Главное медленнее. Но цифрами бросаться все же не стоит.
И это на result += i; Если будут функции с поиском в хэштаблице и ли функции работы со строками,
а учитывая, что в реалии нужно обращаться к данным, которые могут находиться вне кэша памяти, то это отношение будет стремиться к 1!!
То есть ни о каких 1000 и близко нет, но вот если тебе понадобится коллекция то ты на памяти больше потеряешь.
А что мне кэшировать если
1. Данные меняются
2. Мне нужно один раз получить такой итератор с такими условиями.

Кстати в .Net появился ref return

 public class MyIterator
    {
        int Result = 0;
        int state = 0;

       public ref int ReturnResult()
        {
            return ref Result;
        }
       public bool MoveNext()
        {
 
                switch (this.state)
                {
                    case 0:
                    Result = 0;
                    state = 1;
                    return true;
                    
                    case 1:
                    Result++;
                    if (Result == int.MaxValue / 2)
                    {
                        state = 3;
                        return false;
                    }
                    return true;

                       default:
                        return false;
                }


        }

    }


И получать Current по ссылке
 static long RefResult()
        {
            long result = 0;
            var iter = new MyIterator();
            ref int res = ref iter.ReturnResult();

            while (iter.MoveNext())
                result += res;
            return result;
        }

и вызов
r = DateTime.Now;
            result = RefResult();
            var res3 = (DateTime.Now - r).TotalMilliseconds;
            Console.WriteLine(result);
            Console.WriteLine(res3);
            Console.WriteLine($"отношение RefResult к inline {res3 / res}");


То получим
576460750692810753
3235,4582
отношение RefResult к inline 4,327135105321729

То есть ошибся всего в 250 раз!!
Ну в MS считают, что это не принципиально

Но к сожалению такая конструкция

static IEnumerable<int> GetEnumerable2()
        {
            var iter = new MyIterator();
            ref int res = ref iter.ReturnResult();

            while (iter.MoveNext())
                yield return res;
        }


Ругается на ref int res = ref iter.ReturnResult();
Итераторы не могут иметь переменные по ссылке

Но если заменить MoveNext
 public bool MoveNext2(ref int result)
        {

            switch (this.state)
            {
                case 0:
                    Result = 0;
                    state = 1;
                    return true;

                case 1:
                    Result++;
                    if (Result == int.MaxValue / 2)
                    {
                        state = 3;
                        return false;
                    }
                    result = Result;
                    return true;

                default:
                    return false;
            }


        }


И вызов
 static long RefResult2()
        {
            long result = 0;
            var iter = new MyIterator();
            int res = 0;
            while (iter.MoveNext2(ref res))
                result += res;
            return result;

        }


То получим
576460750692810753
3420,4316
отношение RefResult к inline 4,805504333751022

Можно безболезненно и сейчас увеличит производительность, если все итераторы будут наследоваться от одного класса
public class MyIterator<T>
{
public T Result = default(t);

И вызов
static long RefResult3()
        {
            long result = 0;
            var iter = new MyIterator();
            int res = 0;
            while (iter.MoveNext())
                result += iter.Result;
            return result;

        }

Тогда отношение будет всего 3,530814317127427
То есть ошибся ты всего в 300 раз.
Вот и верь тебе!!

Ну не нужно это MS