Здравствуйте, rameel, Вы писали:
V>>Ну какой идентичный, когда речь там шла о безопасности кода? R>Вообще я отвечал на конкретное заявление и речь там шла про эффективность, а не безопасность.
Это называется "потерял контекст" или "заблудился в тёх соснах". ))
Ты ж отвечаешь не на единичное сообщение, а в подветку.
V>>И ты ведь показал итерацию по полному массиву. V>>А теперь проитерируйся по его части, посмотри разницу и помедитируй. R>О том, что нужно проитерироваться по его части речь не шла, это во первых.
Ну и где ты увидел ограничение, что надо проитерировать массив или целиком, или никак?
Это ж попахивает нубством или юлениями, бо в реальном коде массив целиком итерируется крайне редко, т.е. почти никогда.
R>Во вторых, даже если и так, сильной разницы именно сейчас нет, так как если диапазон нам становится известен только в момент, когда мы хотим проитерироваться, то что я выделю из него этот диапазон и пройдусь по нему
Скопируешь в другой массив, что ле?
Что значит "выделю"?
Или, таки, "выделишь" через Span? ))
(что-то уже в голос, сорри... быстро ж ты "поплыл")
R>или сразу буду идти нужный диапазон простым и дубовым кодом через for — сильно ничего не поменяется.
Какое громкое заявление! ))
Ну и что ж ты такой весь в белом притащил тонны ассемблерного кода в предыдущем сообщении, чтобы на весь инет поделиться своими крутыми "знаниями", о которых 99.9% читателей знали еще когда ты пешком под стол ходил еще на бетах дотнета, а теперь почему просто сдулся и выставил себя треплом?
Чтобы не потерять лицо, тебе надо было в предыдущем абзаце сказать всго два слова: "Ой, точно!"
Ну поторопился, ну с кем не бывает...
А сейчас ты себя тупо закопал всем этим идиотизмом.
Кароч, не настолько уж большая была от тебя лажа, чтобы ты так тщательно приступил к юлению.
Теперь взят на карандаш ))
V>>Мой поинт был в следующем: V>>- через Span эффективней (и все более и более популярней в реальном коде); R>Опять общая фраза, но теперь хотя бы контекст виден.
Продолжаешь клоунаду?
Это не "общая фраза", это однозначно понимаемое утверждение, квант знаний в прорве их.
И этот квант стоит учитывать, например, при разработке своих контейнеров вместо тормознутых стандартных (мало ли приспичит).
R>Мой поинт был в том, чтобы указать, не обязательно тебе, на популярное заблуждение, что span эффективней, чем массивы.
Но ты поторопился и ошибся, показав на весь инет, что (а) не владеешь предметом, (б) поленился проверить всевозможные сценарии, (с) не способен признавать косяки.
С таким набором лучше быть ридонли, но тебе зачем-то захотелось общения в этой весовой категории.
R>А спросишь — в чем эффективней — не знают, просто быстрее и точка.
Ты, таки, поитерируй часть массива, посмотри сгенеренную инструкцию CLI, на которую указал Синклер:
в дотнете это специальная инструкция байт-кода, за проверку в ней отвечает среда исполнения
Затем посмотри, что там после джита будет в различных in-force версиях дотнета.
Понимаешь, хотя Синклер, конечно, болтун и склонен преувеличивать (чем зачастую откровенно врёт), но он хотя бы прекрасно понимает, о чём говорит.
Его косяки — они сугубо из-за хождения по грани манипуляций, из-за того, что детстве не пороли за подобное, бгг...
А ты вообще не понимаешь, что тут происходит и зачем.
В общем, извини, но на продемонстрированном тобой уровне понимания как предмета, так и логики взаимных пощипываний, — кыш, кыш, кыш, не мешай взрослым дядькам развлекаться. ))
У них это сугубо ради интеллектуальной физ.зарядки (сорри за тафтологию), ну и местами еще чтобы обкатать собственные мысли или поискать в них дыры усилиями оппонента, бгг...
Здравствуйте, Константин Б., Вы писали:
V>>Макросы плюс библиотечная поддержка. КБ>Ну т.е. каждое разыменование указателя нужно будет в макрос завернуть?
Здравствуйте, vdimas, Вы писали:
V>Это называется "потерял контекст" или "заблудился в тёх соснах". ))
Ты если что спрашивай, подскажу ))
V>Ну и где ты увидел ограничение, что надо проитерировать массив или целиком, или никак? V>Это ж попахивает нубством или юлениями, бо в реальном коде массив целиком итерируется крайне редко, т.е. почти никогда.
Что еще придумаешь?
V>Скопируешь в другой массив, что ле? V>Что значит "выделю"? V>Или, таки, "выделишь" через Span? ))
Выделить диапазон это не обязательно про new, знаешь ли. Впрочем, большего понимания от тебя и не ждут.
V>Ну и что ж ты такой весь в белом притащил тонны ассемблерного кода в предыдущем сообщении, чтобы на весь инет поделиться своими крутыми "знаниями", о которых 99.9% читателей знали еще когда ты пешком под стол ходил еще на бетах дотнета
99.9% читателей может и знали, но это точно не про тебя)
V>Чтобы не потерять лицо, тебе надо было в предыдущем абзаце сказать всго два слова: "Ой, точно!" V>Ну поторопился, ну с кем не бывает...
Обязательно повторяй это по чаще, глядя в зеркало)
V>Продолжаешь клоунаду?
Клоуна здесь только ты из себя изображаешь, но и то не очень как то. Не верю! (с)
V>Но ты поторопился и ошибся, показав на весь инет, что (а) не владеешь предметом, (б) поленился проверить всевозможные сценарии, (с) не способен признавать косяки.
Бросай, все и так знают, что ты (а) не владеешь предметом, (б) поленился проверить всевозможные сценарии, (с) не способен признавать косяки.
V>С таким набором лучше быть ридонли
В точку)
V>но тебе зачем-то захотелось общения в этой весовой категории.
V>Понимаешь, хотя Синклер, конечно, болтун и склонен преувеличивать (чем зачастую откровенно врёт), но он хотя бы прекрасно понимает, о чём говорит. V>Его косяки — они сугубо из-за хождения по грани манипуляций, из-за того, что детстве не пороли за подобное, бгг...
Только все ровно наоборот.
И переставай уже свои детские травмы на других проецировать.
Здравствуйте, Sinclair, Вы писали:
V>>И ты ведь показал итерацию по полному массиву. V>>А теперь проитерируйся по его части, посмотри разницу и помедитируй. S>Вот чего б самому-то не попробовать? S>Не над чем медитировать. S>Вот два тела цикла с итерацией по подмассиву: S>
Слушай, мне аж не верится, что ты на это решился.
"Сгорел сарай — гори и хата!" (С)
Для проверки общего случая достаточно было задать динамически размеры массива и область итерирования:
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-ы как аргументы. (В плюсах к этому давно пришли, еще в либе Boost, откуда оно потом переехало в стандарт — такие вещи оставляют меньше простора для случайных ошибок)
Таким образом, всем коллегам настоятельно рекомендую взять за практику итерировать Span-ы, а не массивы.
Абсолютно безопасный вариант указан мною в сниппете выше.
============
И вообще, это мелочная очевиднейшая хрень, зря ты стал "спасать" того коллегу лишь по факту того, что он попытался поддержать тебя в споре. ))
"Поиск поддержки абы от кого" — признак слабости позиции.
Коллеге достаточно было оставаться предметным в споре, даже если он проворонил общий случай.
Но нет!
Чел не оценил предметности разговора, и понеслась моча по трубам, бгг...
Здравствуйте, vdimas, Вы писали:
V>- штатно отреагировал на ошибку — записал ошибку в системный лог и вернул из вызова (драйверы пишутся по событийной модели) код ошибки с признаком severity=FATAL;
Судя по последним новостям, он валился из-за out of bound memory access. То есть, это не тот случай.
V>- не создал помех в штатном реагировании на ошибку.
Например, не рушился при каждой загрузке системы?
Как ты ни крути, а в этом случае разработчики драйвера облажались.
Здравствуйте, vdimas, Вы писали:
V>Это самое безобидное.
Оно же, крайне нелепое. Взрослым людям использовать такой идиотский ответ не подобает.
V>Мляха, падать в задаче анализа кода!!!
Это вообще не проблема, по сравнению с падением при чтении своих собственных конфигов.
V>Мне уже надоело снисходительно улыбаться на эту дичь.
Если это действительно проблема, давно бы разобрался в причинах и натыкал их носом.
V>Да, я тут малость стебусь, но вряд ли сильно далёк от истины.
Да нет, ты опять гонишь пургу. Во всем виноваты джависты и прочие гнусные дотнетчики, даже если в проекте их вообще нет.
V>Да пофик, что у тебя нет проблем. V>В этом топике мы обсуждаем проблему, которая коснулась менее 1% от всех участвующих в обновлениях компах — и уже получили самый масштабный за всю историю IT сбой.
В твоем случае, больше похоже на < 1e-7%
V>Помножь надёжность Решарпера на огромную кучу нейтивного кода, которая выполняется на твоём компе — и ты просто не смог бы работать.
Хоть решарпер, хоть все прочие проги которые работают на моем компе — глючат примерно одинаково.
V>Не надо считать окружающих за идиотов. V>Иногда стоит сделать паузу и помедитировать над тем, что тебе говорят.
Ну ты же считаешь. Вот и медитируй, если считаешь это нужным.
Здравствуйте, vdimas, Вы писали:
V>В общем, подошли к делу серьезно — и свои различные по стратегиям аллокаторы, и свои эффективные очереди, и эффективная сериализация, и lock-free трюки и прочее.
И при этом запускается несколько секунд, и даже переключение между каналами заметно лагает. Где-то они крупно облажались, и никакие аллокаторы с lock-free не помогли.
V>Да уже заметно разворачивание обратно к нейтиву лицом.
Это в какой альтернативной реальности? Сейчас все больше нового софта делают даже не на яве с дотнетом, а на жабаскрипте со сраным электроном.
Здравствуйте, vdimas, Вы писали:
V>Для проверки общего случая достаточно было задать динамически размеры массива и область итерирования:
Приведённый пример порождается для случая динамического размера массива и области итерирования.
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>
Отож. Как думаете, почему так? И сколько будет проверок, если вместо вызова Console.WriteLine поставить что-то типа s+=array[i], как в исходных примерах?
V>И почему ж ты сам не поисследовал тот код?
Я-то как раз поисследовал. Тем более, что я понимаю, что и почему делает JIT.
V>Я вот поисследовал под 8-м дотнетом и увидел забавное — под линухами JIT сгенерил сразу два цикла — в первый ветвление для случая, когда диапазон заведомо попадает, а во второй — когда не попадает, но итерирование там происходит до момента выхода за границу диапазона.
Именно про это вам писал коллега rameel — "loop cloning". V>Причём, это простейший сниппет.
В этом "простейшем сниппете" вы сравниваете два семантически различных фрагмента кода. Если переписать код так, чтобы фрагменты были семантически эквивалентны, то опять получится одна проверка в цикла.
V>В более общем случае бывают еще выходы из цикла по некоему прикладному условию, бывают оперирования переменной цикла i и т.д.
Бывают. И во всех случаях семантически эквивалентный код порождает эквивалентный asm.
V>>>Теперь-то понятно, зачем сначала рекомендуется брать Span от массива и затем итерироваться? S>>Покамест нет. Проясните, зачем.
V>Итого, даже для простейшего случая выгодней сначала получить Span, а потом итерировать, чтобы не получать после JIT два варианта цикла (два варианта не могут быть бесплатнее одного) и чтобы выбрасывать исключение не после частичного итерования массива, а до.
Ну так JIT за вас не может решить "а давай-ка я буду выбрасывать исключение до того, как будут выполнены Console.WriteLine". Это в С++ UB прямо разрешает компилятору такие вещи — если операция с undefined behavior случается, то это позволяет "произволить" не только результат самой этой операции, но и результаты предшествующих ей операций. А в дотнете стандарт устроен по-другому.
V>Т.е. в указанном виде через array.AsSpan(range) сразу же произойдёт проверка диапазонов, что добавляет происходящему элегантности — ведь это теперь не надо делать вручную самому, как оно было принято за правило хорошего тона до эпохи Span.
Дело не в правиле хорошего тона. Дело в поведении кода. Если у вас по ТЗ нужно сначала вывести все элементы массива, попадающие в заказанный диапазон, и потом выбросить ArrayOutOfBounds, то вы так и пишете, и JIT соответствующим образом это обрабатывает. А если вам по ТЗ нужно сначала убедиться, что заказанный диапазон безопасен, и выкинуть исключение в противном случае, то код без проверки до цикла является ошибкой реализации.
V>И третья причина — цикл foreach выглядит элегантнее цикла for со счётчиком. V>Этот аргумент является совсем уж вкусовщиной и прочими позывами в сторону "избегания синтаксического оверхеда", но, таки, убирание из цикла логики оперирования самим циклом несколько облегчает код, делает его более выразительным. Я такие вещи только приветствую.
V>Таким образом, всем коллегам настоятельно рекомендую взять за практику итерировать Span-ы, а не массивы. V>Абсолютно безопасный вариант указан мною в сниппете выше.
Непонятно, почему вы называете его "абсолютно безопасным". Все приведённые варианты — абсолютно безопасны в том смысле, что там нет ни UB, ни вывода мусора, ни реинтерпретации памяти, ни риска segfault из-за попытки обращения за пределы отмапленного адресного пространства. Программа абсолютно безопасным способом выполняет то, что ей предписано, а в пограничных случаях абсолютно безопасно выкидывает AOOBE.
Разница там — в семантике. Для семантически эквивалентных вариантов можно было бы говорить о разнице в эффективности, но её по факту нет (хотя всего два поста назад вы намекали на обратное).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, 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 честно пытается выполнить некорректный код.
При том, что мы до этого обсуждали, как сделать код более корректным.
Ладно, тут всё ясно.
Ты "объясняешь" то, что объяснять не требуется, т.е. тупо теряешь лицо переводом стрелок, манипулятивным смещением акцентов.
Что часто эффективность и надёжность обеспечивается лишь выбором того или иного способа решения задачи, в т.ч. через техническую эрудицию — знанием уже существующих ср-в.
Здесь и сейчас я тоже говорил о выборе программиста, а не принципах работы JIT.
Принципы работы JIT — это нечто, даваемое сверху.
И всё что ты говорил — оно как раз в пользу моего варианта, даже когда есть побочный эффект Console.WriteLine(item).
Потому что мой вариант выразительнее, позволяет избежать ошибки выхода за диапазон без лишних рукопашных if и лишних рукопашных выбросов исключений, где эта "лишняя работа" по проверке данных на корректность является источником программистских ошибок в 90% случаев в ПО (или даже больший процент). Как раз там или некорректно проверили (особенно диапазоны, бгг, банальные <, <=, +-1 в смещениях и т.д.), или, довольно часто, вовсе не проверили.
Большинство остальных ошибок ПО, которые "логические" — они часто возникают вне программирования, еще на этапе анализа/понимания предметной области и к ошибкам, собсно, реализации задачи ("тупого кодирования") их отнести сложно.
S>Если у вас по ТЗ нужно сначала вывести все элементы массива, попадающие в заказанный диапазон, и потом выбросить ArrayOutOfBounds
Уф, блин...
Боюсь даже представить, что было бы, начни я пороть примерно это же. ))
Тебя бы порвало от счастья, что оппонент по своей воле пожелал настолько жалко выглядеть.
Реально, завязывай уже с этой хернёй.
По ссылке перечитай меня более молодого и более терпеливого (еще) к вашей братии.
Там все ответы на все вопросы.
Посмотри на сам ход мыслей.
Облом повторяться, а в двух словах такие вещи не распишешь.
Думаю, твоя проблема в том, что нужную и правильную весчь озвучил твой оппонент, что не позволяет тебе "просто согласиться".
И еще проблема в том, похоже, что ты пятой точкой чувствуешь засаду, стоит тебе со мной согласиться. ))
На самом деле, вопрос, можно сказать, жизненно важный.
Тут даже можно на время перестать бодаться и озвучить прямой речью:
— использование Span делает код выразительным и эффективным, оставляет меньше простора для ошибок, связанных с формированием диапазонов, позволяет проводить достаточно дешевую декомпозицию алгоритмов над данными;
— одновременно с этим, через Span можно нарваться на ошибки неаккуратности, присущие нейтивным программам в деле прохода по памяти.
Q. Как безопасно использовать Span?
A. Абсолютно все методы и методы-расширения AsSpan(range) безопасны для строк, массивов, объектов Memory<> и ArraySegment. Также безопасны методы самого Span и все прочие объекты/хелперы, которые используют Span через TryRead/TryWrite/TryParse/TryFormat и т.д.
Q. Где можно нарваться на небезопасность даже в случае safe-кода?
A. При использовании для порождения/реинтерпретации ссылок на память с помощью статических методов у типов Unsafe и MemoryMarshal. Здесь ответственность лежит на программисте.
Здравствуйте, Codealot, Вы писали:
V>>- штатно отреагировал на ошибку — записал ошибку в системный лог и вернул из вызова (драйверы пишутся по событийной модели) код ошибки с признаком severity=FATAL; C>Судя по последним новостям, он валился из-за out of bound memory access. То есть, это не тот случай.
Т.е. ты уверен, что драйвер не обработал эту ошибку и не вернул код ошибки с признаком severity=FATAL?
Откуда ты знаешь такие подробности? ))
V>>- не создал помех в штатном реагировании на ошибку. C>Например, не рушился при каждой загрузке системы?
Ну, в 90-х это был "стандартный" сценарий, почти все тогда умели загружать машинку в отладочном режиме, откатывать последние обновления или удалять некий только что установленный драйвер.
Сейчас это стало проблемой лишь от того, что сей навык был утерян массой пользователей.
C>Как ты ни крути, а в этом случае разработчики драйвера облажались.
Разработчики всей системы, бо пока нет точной информации, где именно возникла ошибка.
Есть мутная информация, что ошибка пришла из байт-кода — тогда причина не в драйвере, а в прикладной части, где драйвер лишь даёт прикладной части доступ к защищённым вещам в памяти и файловой системе.
Но даже там ноль подробностей — гуляют две версии, но ни одна из них не заслуживает доверия.
Сдаётся мне, что подробностей и не будет.
На самом деле для спасения лица компании было бы лучше, чтобы ошибка возникла сугубо в нейтиве, бгг...
Потому что если ошибка в прикладной части вызвала такой сбой, то вопросов станет намного больше, ес-но.
Здравствуйте, Codealot, Вы писали:
V>>В общем, подошли к делу серьезно — и свои различные по стратегиям аллокаторы, и свои эффективные очереди, и эффективная сериализация, и lock-free трюки и прочее. C>И при этом запускается несколько секунд
Сравнивал старый и новый тел, загрузка Телеги на старом 4 секунды, на новом примерно полторы.
Вайбер грузится 8 сек и 3, при том что чатов и обновлений на порядки меньше.
C>и даже переключение между каналами заметно лагает.
Это если в канале накопились сотни сообщений — надо скачать информацию как о примерном объеме этих сообщений, так и близлежащие сообщения от последнего прочитанного, чтобы ты смог сразу же листать. На шустром инете это происходит шустро, на мобильном похуже, ес-но.
Посмотри что в таком сценарии происходит в Вайбере и воцапе и ужаснись — ты по нескольку секунд после переключения можешь пялиться на старые сообщения, не видя новые.
Похоже, Вайбер загружает пропущенные сообщения целиком, в отличие от Телеги, которая грузит их поэтапно и приоритезированно, т.е. ты быстрее получишь те сообщения, которые готов уже посмотреть.
В общем, тут Телега выигрывает с разгромным счётом.
И не только у Вайбера — а вообще у всех.
Взять тот же Слак или Тимс, когда накопились сообщения — это даже несравнимо.
Причём, выигрывает, похоже, сугубо за счёт алгоритмов прикладного уровня — когда и в какой последовательности что именно загружать.
А ведь этот прикладной уровень на более прикладных языках как бы более удобно разрабатывать, не? ))
C>Где-то они крупно облажались, и никакие аллокаторы с lock-free не помогли.
Чтобы так утверждать, да еще в таком окученном деле, как мессенджеры, тебе надо показать альтернативы (хотя бы одну), которые работают лучше.
Я, наверно, пользовался всеми популярными мессендерами еще с 90-х и даже близко находящегося по отзывчивости и общему экспиренсу ничего не видел.
V>>Да уже заметно разворачивание обратно к нейтиву лицом. C>Это в какой альтернативной реальности? Сейчас все больше нового софта делают даже не на яве с дотнетом, а на жабаскрипте со сраным электроном.
Тю, это в нише "мобильного интранета".
Что раньше было тяп-ляп интранет для конкретной маленькой конторки, то сейчас переехало в т.ч. на мобилу.
А в коммерческих приложениях — дудки.
Взять даже популярные мобильные приложения от банков — от электронов и прочей HTML-based чепухи постепенно уходят, кроме последних аутсайдеров, типа Тинькоффа, приложение которого открывается до 15-20-ти секунд на мобильном инете, бгг...
Для сравнения, аппликуха основного моего банка предлагает приложить отпечаток уже через секунду после старта, и, после проверки, еще через секунду-полторы, даёт основной GUI-дашборд.
Здравствуйте, vdimas, Вы писали:
V>Потому что чудес не бывает. V>Нельзя одновременно хотеть надёжности не хотеть её.
Ответ неверный.
S>>И сколько будет проверок, если вместо вызова Console.WriteLine поставить что-то типа s+=array[i], как в исходных примерах? V>И это всё еще хуже, чем array.AsSpan(range) по целому комплексу причин, перечисленных мной.
Ну, то есть вы осознали, что промахнулись про эффективность, пришлось переводить разговор на "комплекс причин". Ок, засчитано.
V>Он всего лишь пытается сохранить семантику, даже если семантика содержит ошибку.
Во-первых, с чего вы взяли, что "семантика содержит ошибку"? Возможно, автор так и хотел — вывести не более чем N строк, а AIOOBE успещно перехватывается где-то выше по стеку. V>А мы рассуждали о способах эти ошибки избегать.
Во-вторых, никакого обсуждения способов избегания ошибок не было. Не считать же, в самом деле, выброс AOORE вместо AIOOBE каким-то там "избеганием". V>Видишь насколько дешевы твои манипуляции? ))
Вижу, насколько дёшевы ваши.
V>И да, если тело цикла чуть больше тривиального — он не порождает два варианта, порождается лишь "тяжеловесный".
Давайте посмотрим на какой-нибудь реальный пример.
V>Причём, даже в случае простейшего s+=item, если накопленная сумма s будет доступна и после выброса исключения, то в этот ошибочный вариант заходит и долго пыхтит перед тем, как выбросить исключение.
Повторю неочевидную для вас вещь: такое поведение связано не с плохим качеством оптимизатора, а с требованиями стандарта. "Ошибочность" варианта локально оценить невозможно. V>А на деле, уровнем выше, эта s уже не нужна, но JIT не способен смотреть слишком далеко, пытаясь разгадать намерения программиста.
JIT способен смотреть ровно настолько, сколько попало в его поле зрения. Как, впрочем, и более-менее любой компилятор. Чтобы любой компилятор понял, что s уже не нужна, ему нужно "видеть" весь использующий её код.
Стандартная методика для оптимизаций обсуждаемого типа — инлайнинг. Работает это и в JIT-ах дотнета и джавы, и в GCC, и в LLVM. Нет инлайнинга — нет возможности гарантировать отсутствие побочных эффектов — будь любезен породить семантически корректный код.
V>Ес-но, мы же о безопасности рассуждали.
Неа, вы рассуждали об эффективности. Но пытаетесь мухлевать, как обычно.
V>За это тебя и не любят в спорах.
За то, что я внимательно читаю, и точно пишу?
V>Разумеется, можно вручную обвешать код проверками и облегчить жизнь JIT-у.
V>А еще можно вспомнить, что это стало работать вот совсем недавно по меркам жизни дотнета, что сколько я ни смотрел тщательно на выхлоп в течении двух десятков лет — он рожал "тяжелый" цикл, собака.
V>А еще коммерческие продукты должны поддерживать все дотнетные версии, которые официально в ходу, т.е. приходилось ориентироваться на то, что происходит, скажем, в .Net Core 3.1, даже когда уже вышел .Net 6.0.
V>У меня сейчас такое ощущение, что мы с тобой поменялись местами в споре — я топлю за безопасность и выразительность, а ты возражаешь "но если постараться, то ведь можно и ручками допилить примерно до такого же".
Не, вы одновременно мухлюете в нескольких направлениях. Например, делаете вид, что не пытались выдать устаревшие знания про оптимизацию циклов в дотнете за какие-то особенные знания, одновременно делая вид, что два кода, выбрасывающих исключения, чем-то отличаются друг от друга в плане безопасности.
V>Ну так решение может принять программист.
Может, конечно. V>Просто ты никак не можешь под этим подписаться, бгг...
Нет, просто утверждение про то, что Span — более эффективный способ итерироваться по массиву устарело примерно тогда же, когда в джит завезли собственно оптимизации Span.
V>Мне забавно, конечно, что ты как аргумент предъявляешь то, что JIT честно пытается выполнить некорректный код. V>При том, что мы до этого обсуждали, как сделать код более корректным.
И как вы определяете, какой из сниппетов более корректный? V>Ладно, тут всё ясно.
Отож.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vdimas, Вы писали:
V>Сравнивал старый и новый тел, загрузка Телеги на старом 4 секунды, на новом примерно полторы.
Всего то На десктопе примерно столько же.
V>Это если в канале накопились сотни сообщений — надо скачать информацию как о примерном объеме этих сообщений, так и близлежащие сообщения от последнего прочитанного, чтобы ты смог сразу же листать. На шустром инете это происходит шустро, на мобильном похуже, ес-но.
Это происходит и тогда, когда новых сообщений вообще нет.
Так что, закэшировать локально нельзя? Сначала показать старые, потом добавить новые?
Да не, это все забытые технологии древних цивилизаций.
V>Чтобы так утверждать, да еще в таком окученном деле, как мессенджеры, тебе надо показать альтернативы (хотя бы одну), которые работают лучше.
А зачем, собственно? Ты не можешь сам посчитать и прикинуть цифры?
V>Тю, это в нише "мобильного интранета".
Здравствуйте, vdimas, Вы писали:
V>Т.е. ты уверен, что драйвер не обработал эту ошибку и не вернул код ошибки с признаком severity=FATAL?
А у тебя есть данные, что обработал? =)) Ты сам гадаешь на кофейной гуще, но все равно делаешь далеко идущие выводы.
А вообще странно. Неужели даже конкретной инфы, что там за бсод, нигде нет?
V>Сейчас это стало проблемой лишь от того, что сей навык был утерян массой пользователей.
Уверен, что этому нет никаких других причин?
V>тогда причина не в драйвере, а в прикладной части, где драйвер лишь даёт прикладной части доступ к защищённым вещам в памяти и файловой системе.
Тогда нет причин, почему эту ошибку нельзя обработать, не обрушивая систему.
Здравствуйте, Codealot, Вы писали:
V>>Сравнивал старый и новый тел, загрузка Телеги на старом 4 секунды, на новом примерно полторы. C>Всего то На десктопе примерно столько же.
Ну так тел же перегружается крайне редко, даже не каждый месяц, так что в обычном сценарии под видом запуска приложения тычком по пиктограмме происходит переключение на уже открытое несколькими неделями раньше приложение, это вообще доли секунд.
V>>Это если в канале накопились сотни сообщений — надо скачать информацию как о примерном объеме этих сообщений, так и близлежащие сообщения от последнего прочитанного, чтобы ты смог сразу же листать. На шустром инете это происходит шустро, на мобильном похуже, ес-но. C>Это происходит и тогда, когда новых сообщений вообще нет. C>Так что, закэшировать локально нельзя? Сначала показать старые, потом добавить новые? C>Да не, это все забытые технологии древних цивилизаций.
Это всего лишь вопрос выбора стратегии.
На старом медленном интернете, разумеется, имело смысл сначала показать старое, а потом уже подгружать новое.
На быстром инете имеет смысл подгрузить несколько новых сообщений перед переключением в другой канал/чат плюс информацию о кол-ве непрочитанных сообщений, чтобы сразу же читать ближайшие новые сообщения и видеть, сколько всего непрочитанных.
V>>Чтобы так утверждать, да еще в таком окученном деле, как мессенджеры, тебе надо показать альтернативы (хотя бы одну), которые работают лучше. C>А зачем, собственно? Ты не можешь сам посчитать и прикинуть цифры?
Что и как считать?
Я почти не пользовался Телегой до СВО, как и большинство знакомых (потому и не пользовался — ведь это был, в основном, yet another messanger).
Но баны на ютубе и других платформах, плюс удобство ведения каналов в Телеге резко повысили популярность телеги в странах экс-СССР с началом СВО.
И вот тут сравнил с привычными до этого вайберами, воцапами, слаками, скайпами, зумами и т.д.
Если инет не совсем дохлый, то Телега удобнее в разы как для ленты новостей, "плоского" форума, так и в кач-ве обычного чата с контактами или в группах.
По крайней мере, чаты всех групп, в которых состоял, за эти 2 с лишним года переехали с вайберов/воцапов/скайпов в телегу, и не по моей инициативе.
Т.е. народ дружно сошёлся во мнении, что Телега удобней/приятней.
V>>Тю, это в нише "мобильного интранета". C>К сожалению, не только.
Ну вот был у меня клиент-банк еще одного неосновного моего банка (у меня их пяток) — приложуха от банка Точки.
Тормознутое г-но когда-то.
В прошлом году полностью переписали — теперь летает.
А взять клиент-банк ОТП-банка (бизнес-клиент), дык, он изначально, такое ощущение, что на чём-то совсем нейтивном работает, типа QT (на правах гипотезы), бо работает совсем мгновенно, хотя у него и не самый удобный GUI (больше кликов надо для того же).
Здравствуйте, Codealot, Вы писали:
V>>Т.е. ты уверен, что драйвер не обработал эту ошибку и не вернул код ошибки с признаком severity=FATAL? C>А у тебя есть данные, что обработал? =)) Ты сам гадаешь на кофейной гуще, но все равно делаешь далеко идущие выводы.
Да потому что у любой виденной мною виртуальной машинки есть ср-ва реагирования на ошибки в байт-коде.
Отсюда и предполагаю, что вызвавшая сбой ошибка в байт-коде была расценена VM как фатальная, т.е. "невозможно продолжать работу".
Это просто единственный сценарий, который ложится на опыт работы со многими виденными байт-машинками и интерпретаторами p-кода, и не более того, ес-но.
А предполагаемые Синклером причины (его там слишком несло, почему я и вмешался) — они попахивают фантастикой, противоречат даже его собственному опыту, бгг...
Точных деталей ни у меня, ни у него нет, понятно, но если брать вероятности из опыта индустрии — то Синклер однозначно гонит.
Его предположения, даже если ему очень хотелось, чтобы было именно так, необходимо было преподносить аккуратно и с оговоркой, что вероятность исчезающе мала.
Т.е. налицо тупая ангажированность.
C>А вообще странно. Неужели даже конкретной инфы, что там за бсод, нигде нет?
Есть картинки в инете, там два кода ошибки, и?
Это ж надо посмотреть системный лог и загрузить дамп в память отладчика, чтобы оттрассировать произошедшее.
А если рядом не положить PDB — то раскопать реально произошедшее будет оч сложно.
Т.е., проще всего это сделать разрабам, конечно, которые обязаны компилять релизы с PDB, и хранить их у себя как раз для таких случаев.
V>>Сейчас это стало проблемой лишь от того, что сей навык был утерян массой пользователей. C>Уверен, что этому нет никаких других причин?
Если я вижу в инете пошаговую инструкцию для этого сбоя "загрузиться в отладочном режиме и откатить обновление"?
Видя такую "инструкцию" уже не знаешь — плакать или смеяться. ))
V>>тогда причина не в драйвере, а в прикладной части, где драйвер лишь даёт прикладной части доступ к защищённым вещам в памяти и файловой системе. C>Тогда нет причин, почему эту ошибку нельзя обработать, не обрушивая систему.
Своё предположение я уже выдал — тут стоит помнить, что это система по обеспечению безопасности.
И что причина существования модуля драйвера этой системы — это предоставлять остальной части доступ к памяти других процессов и к защищённым файлам.
Т.е., косяки в байт-коде могут означать скомпрометированность системы, например, в результате атаки.
В этом случае драйверу лучше отвалиться, чем продолжать предоставлять в юзверское кольцо исполнения дыру для доступа куда угодно.
Здравствуйте, Codealot, Вы писали:
V>>Это самое безобидное. C>Оно же, крайне нелепое. Взрослым людям использовать такой идиотский ответ не подобает.
Ну, я обычно использую "правило 3-х раз", когда коллега переходит все границы в общении.
У тебя это уже второй, бгг...
В общем, стоит отделять случайные эманации от преднамеренной зловредности.
=========
По этой же причине я не одобряю взаимные упрёки в демагогии — это неконструктивно.
Обструкции стоит подвергать намеренные манипуляции.
В этом смыслу обвинение в демагогии (да еще по незначащим вещам) — тоже разновидность манипуляции.
Рассуждения тут такие — демагогия часто бывает непреднамеренной, из-за неудачного аргументирования и т.д., т.е. сам факт случайного прибегания к демагогии еще не означает, что оппонент ошибается — чаще в спорах это означает лишь, что аргументация хромает и могла бы быть чуть лучше.
Другое дело, когда к демагогии прибегают систематически с целью манипуляций, да и вообще спор идёт не ради добычи полезной инфы или установления истины, а ради желания некоторых почесать своё ЧСВ (или, наоборот, полелеять комплексы/мозоли) за счёт других.
Вот тут я позволяю себе резкости — у меня дофига нарушений и банов. ))
Ну а что делать с подлецами?