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

Сообщение Re[20]: А чего молчим про Crowdstrike от 30.07.2024 11:42

Изменено 30.07.2024 11:46 vdimas

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

V>>Для проверки общего случая достаточно было задать динамически размеры массива и область итерирования:

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

S>Отож. Как думаете, почему так?

Потому что чудес не бывает.
Нельзя одновременно хотеть надёжности не хотеть её.


S>И сколько будет проверок, если вместо вызова Console.WriteLine поставить что-то типа s+=array[i], как в исходных примерах?


И это всё еще хуже, чем array.AsSpan(range) по целому комплексу причин, перечисленных мной.


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

S>Я-то как раз поисследовал. Тем более, что я понимаю, что и почему делает JIT.

А что тут понимать-то?
Он всего лишь пытается сохранить семантику, даже если семантика содержит ошибку.
А мы рассуждали о способах эти ошибки избегать.

Видишь насколько дешевы твои манипуляции? ))
"Следим за левой рукой, а фокус производим правой", бгг...

И да, если тело цикла чуть больше тривиального — он не порождает два варианта, порождается лишь "тяжеловесный".

Причём, даже в случае простейшего s+=item, если накопленная сумма s будет доступна и после выброса исключения, то в этот ошибочный вариант заходит и долго пыхтит перед тем, как выбросить исключение.
А на деле, уровнем выше, эта s уже не нужна, но JIT не способен смотреть слишком далеко, пытаясь разгадать намерения программиста.

Все эти доводы ты и сам знаешь как отче наш, но сам себе их не привёл перед тем, как спорить.
Вот цена обсуждений с тобой, бгг...


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

S>Именно про это вам писал коллега rameel — "loop cloning".

С ограничениями:

You must use int, the condition should be less than, increment gap should be one.



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

S>В этом "простейшем сниппете" вы сравниваете два семантически различных фрагмента кода.

Ес-но, мы же о безопасности рассуждали.


S>Если переписать код так, чтобы фрагменты были семантически эквивалентны, то опять получится одна проверка в цикла.


Вооот!
За это тебя и не любят в спорах.

В нейтиве ровно та же фигня "если бы" (С)
Ведь зародыш будущей ошибки появляется ровно тогда, когда самоуверенный или ленивый программист не делает лишних проверок.

Разумеется, можно вручную обвешать код проверками и облегчить жизнь JIT-у.
А еще можно вспомнить, что это стало работать вот совсем недавно по меркам жизни дотнета, что сколько я ни смотрел тщательно на выхлоп в течении двух десятков лет — он рожал "тяжелый" цикл, собака.

А еще коммерческие продукты должны поддерживать все дотнетные версии, которые официально в ходу, т.е. приходилось ориентироваться на то, что происходит, скажем, в .Net Core 3.1, даже когда уже вышел .Net 6.0.

Это реальность, в которой приходилось и приходится принимать решения.


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

S>Бывают. И во всех случаях семантически эквивалентный код порождает эквивалентный asm.

Хотя на практике требуется совсем другое — безопасный и быстрый код при более-менее синтаксической эквивалентности, и, желательно, еще большей синтаксической выразительности.

================
У меня сейчас такое ощущение, что мы с тобой поменялись местами в споре — я топлю за безопасность и выразительность, а ты возражаешь "но если постараться, то ведь можно и ручками допилить примерно до такого же".

Думаю, твоя проблема в том, что нужную и правильную весчь озвучил твой оппонент, что не позволяет тебе "просто согласиться".


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

S>Ну так JIT за вас не может решить "а давай-ка я буду выбрасывать исключение до того, как будут выполнены Console.WriteLine". Это в С++ UB прямо разрешает компилятору такие вещи — если операция с undefined behavior случается, то это позволяет "произволить" не только результат самой этой операции, но и результаты предшествующих ей операций. А в дотнете стандарт устроен по-другому.

Ну так решение может принять программист.
Просто ты никак не можешь под этим подписаться, бгг...


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

S>Дело не в правиле хорошего тона. Дело в поведении кода.

Дело в корректности кода.

Мне забавно, конечно, что ты как аргумент предъявляешь то, что JIT честно пытается выполнить некорректный код.
При том, что мы до этого обсуждали, как сделать код более корректным.

Ладно, тут всё ясно.

Ты "объясняешь" то, что объяснять не требуется, т.е. тупо теряешь лицо переводом стрелок, манипулятивным смещением акцентов.

Я когда рассуждал о том, что "эффективность" не обязана быть дорогой:
https://www.rsdn.org/forum/philosophy/1462269

Что часто эффективность и надёжность обеспечивается лишь выбором того или иного способа решения задачи, в т.ч. через техническую эрудицию — знанием уже существующих ср-в.

Здесь и сейчас я тоже говорил о выборе программиста, а не принципах работы JIT.
Принципы работы JIT — это нечто, даваемое сверху.

И всё что ты говорил — оно как раз в пользу моего варианта, даже когда есть побочный эффект Console.WriteLine(item).

Потому что мой вариант выразительнее, позволяет избежать ошибки выхода за диапазон без лишних рукопашных if и лишних рукопашных выбросов исключений, где эта "лишняя работа" по проверке данных на корректность является источником программистских ошибок в 90% случаев в ПО (или даже больший процент).

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


S>Если у вас по ТЗ нужно сначала вывести все элементы массива, попадающие в заказанный диапазон, и потом выбросить ArrayOutOfBounds


Уф, блин...
Боюсь даже представить, что было бы, начни я пороть примерно это же. ))
Тебя бы порвало от счастья, что оппонент по своей воле пожелал настолько жалко выглядеть.

Реально, завязывай уже с этой хернёй.
По ссылке перечитай меня более молодого и более терпеливого (еще) к вашей братии.
Там все ответы на все вопросы.
На сам ход мыслей.
Re[20]: А чего молчим про Crowdstrike
Здравствуйте, Sinclair, Вы писали:

V>>Для проверки общего случая достаточно было задать динамически размеры массива и область итерирования:

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

S>Отож. Как думаете, почему так?

Потому что чудес не бывает.
Нельзя одновременно хотеть надёжности не хотеть её.


S>И сколько будет проверок, если вместо вызова Console.WriteLine поставить что-то типа s+=array[i], как в исходных примерах?


И это всё еще хуже, чем array.AsSpan(range) по целому комплексу причин, перечисленных мной.


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

S>Я-то как раз поисследовал. Тем более, что я понимаю, что и почему делает JIT.

А что тут понимать-то?
Он всего лишь пытается сохранить семантику, даже если семантика содержит ошибку.
А мы рассуждали о способах эти ошибки избегать.

Видишь насколько дешевы твои манипуляции? ))
"Следим за левой рукой, а фокус производим правой", бгг...

И да, если тело цикла чуть больше тривиального — он не порождает два варианта, порождается лишь "тяжеловесный".

Причём, даже в случае простейшего s+=item, если накопленная сумма s будет доступна и после выброса исключения, то в этот ошибочный вариант заходит и долго пыхтит перед тем, как выбросить исключение.
А на деле, уровнем выше, эта s уже не нужна, но JIT не способен смотреть слишком далеко, пытаясь разгадать намерения программиста.

Все эти доводы ты и сам знаешь как отче наш, но сам себе их не привёл перед тем, как спорить.
Вот цена обсуждений с тобой, бгг...


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

S>Именно про это вам писал коллега rameel — "loop cloning".

С ограничениями:

You must use int, the condition should be less than, increment gap should be one.



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

S>В этом "простейшем сниппете" вы сравниваете два семантически различных фрагмента кода.

Ес-но, мы же о безопасности рассуждали.


S>Если переписать код так, чтобы фрагменты были семантически эквивалентны, то опять получится одна проверка в цикла.


Вооот!
За это тебя и не любят в спорах.

В нейтиве ровно та же фигня "если бы" (С)
Ведь зародыш будущей ошибки появляется ровно тогда, когда самоуверенный или ленивый программист не делает лишних проверок.

Разумеется, можно вручную обвешать код проверками и облегчить жизнь JIT-у.
А еще можно вспомнить, что это стало работать вот совсем недавно по меркам жизни дотнета, что сколько я ни смотрел тщательно на выхлоп в течении двух десятков лет — он рожал "тяжелый" цикл, собака.

А еще коммерческие продукты должны поддерживать все дотнетные версии, которые официально в ходу, т.е. приходилось ориентироваться на то, что происходит, скажем, в .Net Core 3.1, даже когда уже вышел .Net 6.0.

Это реальность, в которой приходилось и приходится принимать решения.


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

S>Бывают. И во всех случаях семантически эквивалентный код порождает эквивалентный asm.

Хотя на практике требуется совсем другое — безопасный и быстрый код при более-менее синтаксической эквивалентности, и, желательно, еще большей синтаксической выразительности.

================
У меня сейчас такое ощущение, что мы с тобой поменялись местами в споре — я топлю за безопасность и выразительность, а ты возражаешь "но если постараться, то ведь можно и ручками допилить примерно до такого же".

Думаю, твоя проблема в том, что нужную и правильную весчь озвучил твой оппонент, что не позволяет тебе "просто согласиться".


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

S>Ну так JIT за вас не может решить "а давай-ка я буду выбрасывать исключение до того, как будут выполнены Console.WriteLine". Это в С++ UB прямо разрешает компилятору такие вещи — если операция с undefined behavior случается, то это позволяет "произволить" не только результат самой этой операции, но и результаты предшествующих ей операций. А в дотнете стандарт устроен по-другому.

Ну так решение может принять программист.
Просто ты никак не можешь под этим подписаться, бгг...


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

S>Дело не в правиле хорошего тона. Дело в поведении кода.

Дело в корректности кода.

Мне забавно, конечно, что ты как аргумент предъявляешь то, что JIT честно пытается выполнить некорректный код.
При том, что мы до этого обсуждали, как сделать код более корректным.

Ладно, тут всё ясно.

Ты "объясняешь" то, что объяснять не требуется, т.е. тупо теряешь лицо переводом стрелок, манипулятивным смещением акцентов.

Я когда-то рассуждал о том, что "эффективность" не обязана быть дорогой:
https://www.rsdn.org/forum/philosophy/1462269

Что часто эффективность и надёжность обеспечивается лишь выбором того или иного способа решения задачи, в т.ч. через техническую эрудицию — знанием уже существующих ср-в.

Здесь и сейчас я тоже говорил о выборе программиста, а не принципах работы JIT.
Принципы работы JIT — это нечто, даваемое сверху.

И всё что ты говорил — оно как раз в пользу моего варианта, даже когда есть побочный эффект Console.WriteLine(item).

Потому что мой вариант выразительнее, позволяет избежать ошибки выхода за диапазон без лишних рукопашных if и лишних рукопашных выбросов исключений, где эта "лишняя работа" по проверке данных на корректность является источником программистских ошибок в 90% случаев в ПО (или даже больший процент).

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


S>Если у вас по ТЗ нужно сначала вывести все элементы массива, попадающие в заказанный диапазон, и потом выбросить ArrayOutOfBounds


Уф, блин...
Боюсь даже представить, что было бы, начни я пороть примерно это же. ))
Тебя бы порвало от счастья, что оппонент по своей воле пожелал настолько жалко выглядеть.

Реально, завязывай уже с этой хернёй.
По ссылке перечитай меня более молодого и более терпеливого (еще) к вашей братии.
Там все ответы на все вопросы.
На сам ход мыслей.