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

Сообщение Re[18]: А чего молчим про Crowdstrike от 29.07.2024 15:52

Изменено 29.07.2024 16:19 vdimas

Re[18]: А чего молчим про Crowdstrike
Здравствуйте, Sinclair, Вы писали:

V>>И ты ведь показал итерацию по полному массиву.

V>>А теперь проитерируйся по его части, посмотри разницу и помедитируй.
S>Вот чего б самому-то не попробовать?
S>Не над чем медитировать.
S>Вот два тела цикла с итерацией по подмассиву:
S>
S>    L0020: mov ecx, r8d
S>    L0023: add eax, [rdx+rcx*4+0x10]
S>    L0027: inc r8d
S>    L002a: cmp r8d, r9d
S>    L002d: jl short L0020
S>


S>
S>    L002f: mov r8d, edx
S>    L0032: add eax, [rcx+r8*4]
S>    L0036: inc edx
S>    L0038: cmp edx, r9d
S>    L003b: jl short L002f
S>

S>Какое из них — от Span, какое — от int[]?

Хахаха

Слушай, мне аж не верится, что ты на это решился.
"Сгорел сарай — гори и хата!" (С)

Для проверки общего случая достаточно было задать динамически размеры массива и область итерирования:
       int count1 = Convert.ToInt32(Console.ReadLine());
       int[] array = new int[count1];

       int count2 = Convert.ToInt32(Console.ReadLine());

       for(int i = 0; i < count2; i++)
            Console.WriteLine(array[i]); 

       var span = array.AsSpan(0, count2);

       foreach(var i in span)
            Console.WriteLine(i);


И получишь две проверки в цикле для массива, как и ожидается:
G_M27646_IG16:  ;; offset=0x010B
       cmp      r14d, dword ptr [rbx+0x08]
       jae      SHORT G_M27646_IG23
       mov      edi, r14d
       mov      edi, dword ptr [rbx+4*rdi+0x10]
       call     [System.Console:WriteLine(int)]
       inc      r14d
       cmp      r14d, r15d
       jl       SHORT G_M27646_IG16


V>>Для итерации по полному массиву брать Span не требуется, конечно.

S>И по неполному — тоже

И почему ж ты сам не поисследовал тот код?

Я вот поисследовал под 8-м дотнетом и увидел забавное — под линухами JIT сгенерил сразу два цикла — в первый ветвление для случая, когда диапазон заведомо попадает, а во второй — когда не попадает, но итерирование там происходит до момента выхода за границу диапазона.

Причём, это простейший сниппет.

В более общем случае бывают еще выходы из цикла по некоему прикладному условию, бывают оперирования переменной цикла i и т.д.
Для таких более общих случаев был сгенерирован один вариант цикла — тот самый, который "тяжелый", разумеется.


V>>Теперь-то понятно, зачем сначала рекомендуется брать Span от массива и затем итерироваться?

S>Покамест нет. Проясните, зачем.

Итого, даже для простейшего случая выгодней сначала получить Span, а потом итерировать, чтобы не получать после JIT два варианта цикла (два варианта не могут быть бесплатнее одного) и чтобы выбрасывать исключение не после частичного итерования массива, а до.
Т.е. в указанном виде через array.AsSpan(range) сразу же произойдёт проверка диапазонов, что добавляет происходящему элегантности — ведь это теперь не надо делать вручную самому, как оно было принято за правило хорошего тона до эпохи Span.

Таким образом, всем коллегам я настоятельно рекомендую взять за практику итерировать Span-ы, а не массивы.

============
И вообще, это мелочная очевиднейшая хрень, зря ты стал "спасать" того коллегу лишь по факту того, что он попытался поддержать тебя в споре. ))
"Поиск поддержки абы от кого" — признак слабости позиции.

Я ответил коллеге абсолютно корректно в первый раз:
https://www.rsdn.org/forum/flame.comp/8787342.1

Коллеге достаточно было оставаться предметным в споре, даже если он проворонил общий случай.
Но нет!
Чел не оценил предметности разговора, и понеслась моча по трубам, бгг...
Re[18]: А чего молчим про Crowdstrike
Здравствуйте, Sinclair, Вы писали:

V>>И ты ведь показал итерацию по полному массиву.

V>>А теперь проитерируйся по его части, посмотри разницу и помедитируй.
S>Вот чего б самому-то не попробовать?
S>Не над чем медитировать.
S>Вот два тела цикла с итерацией по подмассиву:
S>
S>    L0020: mov ecx, r8d
S>    L0023: add eax, [rdx+rcx*4+0x10]
S>    L0027: inc r8d
S>    L002a: cmp r8d, r9d
S>    L002d: jl short L0020
S>


S>
S>    L002f: mov r8d, edx
S>    L0032: add eax, [rcx+r8*4]
S>    L0036: inc edx
S>    L0038: cmp edx, r9d
S>    L003b: jl short L002f
S>

S>Какое из них — от Span, какое — от int[]?

Хахаха

Слушай, мне аж не верится, что ты на это решился.
"Сгорел сарай — гори и хата!" (С)

Для проверки общего случая достаточно было задать динамически размеры массива и область итерирования:
       int count1 = Convert.ToInt32(Console.ReadLine());
       int[] array = new int[count1];

       int count2 = Convert.ToInt32(Console.ReadLine());

       for(int i = 0; i < count2; i++)
            Console.WriteLine(array[i]); 

       var span = array.AsSpan(0, count2);

       foreach(var i in span)
            Console.WriteLine(i);


И получишь две проверки в цикле для массива, как и ожидается:
G_M27646_IG16:  ;; offset=0x010B
       cmp      r14d, dword ptr [rbx+0x08]
       jae      SHORT G_M27646_IG23
       mov      edi, r14d
       mov      edi, dword ptr [rbx+4*rdi+0x10]
       call     [System.Console:WriteLine(int)]
       inc      r14d
       cmp      r14d, r15d
       jl       SHORT G_M27646_IG16


V>>Для итерации по полному массиву брать Span не требуется, конечно.

S>И по неполному — тоже

И почему ж ты сам не поисследовал тот код?

Я вот поисследовал под 8-м дотнетом и увидел забавное — под линухами JIT сгенерил сразу два цикла — в первый ветвление для случая, когда диапазон заведомо попадает, а во второй — когда не попадает, но итерирование там происходит до момента выхода за границу диапазона.

Причём, это простейший сниппет.

В более общем случае бывают еще выходы из цикла по некоему прикладному условию, бывают оперирования переменной цикла i и т.д.
Для таких более общих случаев был сгенерирован один вариант цикла — тот самый, который "тяжелый", разумеется.


V>>Теперь-то понятно, зачем сначала рекомендуется брать Span от массива и затем итерироваться?

S>Покамест нет. Проясните, зачем.

Итого, даже для простейшего случая выгодней сначала получить Span, а потом итерировать, чтобы не получать после JIT два варианта цикла (два варианта не могут быть бесплатнее одного) и чтобы выбрасывать исключение не после частичного итерования массива, а до.

Т.е. в указанном виде через array.AsSpan(range) сразу же произойдёт проверка диапазонов, что добавляет происходящему элегантности — ведь это теперь не надо делать вручную самому, как оно было принято за правило хорошего тона до эпохи Span.

И третья причина — цикл foreach выглядит элегантнее цикла for со счётчиком.
Этот аргумент является совсем уж вкусовщиной и прочими позывами в сторону "избегания синтаксического оверхеда", но, таки, убирание из цикла логики оперирования самим циклом несколько облегчает код, делает его более выразительным. Я такие вещи только приветствую.

Третья с половиной причина — из-за декомпозиции задач формирования диапазона и итерирования, можно (опять элегантно) декомпозировать код, т.е. передавать/возвращать Span-ы как аргументы.

Таким образом, всем коллегам настоятельно рекомендую взять за практику итерировать Span-ы, а не массивы.
Абсолютно безопасный вариант указан мною в сниппете выше.

============
И вообще, это мелочная очевиднейшая хрень, зря ты стал "спасать" того коллегу лишь по факту того, что он попытался поддержать тебя в споре. ))
"Поиск поддержки абы от кого" — признак слабости позиции.

Я ответил коллеге абсолютно корректно в первый раз:
https://www.rsdn.org/forum/flame.comp/8787342.1

Коллеге достаточно было оставаться предметным в споре, даже если он проворонил общий случай.
Но нет!
Чел не оценил предметности разговора, и понеслась моча по трубам, бгг...