Здравствуйте, Sinclair, Вы писали:
V>>Да ложь это.
S>Нет, это вы не понимаете.
Опять эзотерика? ))
Не надоело?
V>>Проверка индекса при доступе к массивам — это фича конкретного объекта, а не среды исполнения.
S>Смотря как реализован доступ к массивам. Например, в дотнете это специальная инструкция байт-кода, за проверку в ней отвечает среда исполнения.
Я и сказал ниже, что некоторые объекты JIT "знает в лицо".
И это не самый эффективный способ итерации по массивам и вообще по данным — не зря сейчас рекомендуют получать Span, и итерироваться уже по нему.
При этом есть способы получения Span, указывающего на произвольный мусор в памяти, с произвольной его интерпретацией или с затиранием произвольного куска памяти, что можно покоцать даже саму VM.
S>Не получится руками сделать такой же "объект" и не сделать проверку.
Это если бы не существовали другие способы — например, есть опкод получения адреса первого элемента массива, именно так читаются составные структуры из массивов.
А затем в опкодах можно этот адрес тупо приращать — и никакой "верификатор-загрузчик" тебе и слова не скажет, бгг...
Но и это слишком сложно, бо массивы тут вовсе не обязательны — бери тело любого объекта, получай ссылку на поле и поступай как описано выше.
Или бери ссылку на локальную переменную/аргумент и т.д.
Кароч, способов развязать руки на манер голого Си полно.
И ты это прекрасно знаешь. ))
Но упорно приводишь в пример лишь безопасные способы.
В любом языке аналогичные безопасные способы есть, конечно, но мы же ругаем языки за наличие опасных способов, т.е. исходя из того, что программисты слишком самоуверенны, но людям свойственно ошибаться.
Так вот, повторю, в дотнете с появлением "официальной" либы Unsafe всё стало ровно так же, как в плюсах, в плане возможностей случайно нагадить.
И даже больше, бо нет детерминированного освобождения ресурсов, т.е. RAII весьма опциональный, а не обязательный.
V>>Запросто в опкодах получай ссылку на данные и лезь по произвольному индексу, гадя в произвольную память, бгг...
S>Это зависит от конкретной среды исполнения. Можно убрать unmanaged pointers, и возможность "лезть по произвольному индексу" исчезнет.
Да без проблем — используй managed ссылки.
Это ты был не в курсе или опять прилюдно ломаешь комедию? ))
V>>Проверка на null перед вызовом метода объекта?
V>>Это и вовсе фича компилятора конкретного языка, который подставляет callvirt вместо call.
S>Вы почему-то думаете, что дотнетом исчерпывается мир виртуальных машин. Нет, это не так. Дотнет — компромиссная технология, в нём пришлось принять ряд спорных решений.
Хорошее слово "пришлось".
Этих "пришлось" было несколько, включая АОТ.
Мне иногда кажется, что JNI с джаве сделали как сделали лишь с той целью, чтобы сопряжение с нейтивом выполняли люди, специализирующиеся на другой технологии.
Потому что дотнет запросто валится даже от корявого P/Invoke, описанного разрабами с другой "планкой входа", бгг...
А ты думаешь, отчего AVK одно время стал настолько раздражителен и спесив, что даже взял второй ник?
Да потому что работает с такими людьми и на фоне их кажется сам себе гигантом мысли, ес-но.
Но нервные клетки, таки, сильно страдают, от непокидающего вечного раздражения.
S>Это не означает, что сама по себе идея управляемых сред неверна.
А никто и не говорил, что эта идея не верна.
Освежи обсуждения еще с 2004-2005-х годов — всегда критиковались лишь завышенные ожидания от этой технологии.
Почему?
Потому что завышенные ожидания выглядят слабостью, эдакой "уважительной причиной" расслабить булки.
И никто не говорил, что GC — днище.
Говорилось другое — что не для всех задач это самая удачная технология.
Скажу так, с какого-то момента в .Net Core у меня вдруг стали резко развязаны руки в плане проектирования данных и алгоритмов, в том числе обобщённых, в том числе, работающих поверх графов неуправляемой памяти наряду с управляемой. А всего-то добавили ограничение unmanaged в генерики и обкатали Span/Memory и... тадаам — обобщили работу с памятью через MemoryManager и паттерны вокруг MemoryHandle. Это было фуф, вытереть пот со лба, наконец-то можно было просто программировать себе без вечного ощущения раздражения из-за убогости доступных платформенных ср-в.
Когда они догадались сделать ref struct одновременно с readonly ref return — да я просто офигел, насколько же там прибавилось здравого смысла у разрабов. ))
Однозначно лайк! ))
Это они одним махом решили очень нетривиальную задачку, которую мы так и не смогли решить эффектвно, на манер как в плюсах — были вынуждены создавать копии данных перед вызовами юзверских колбэков, потому что иначе создавалась дыра — не было защиты от дурака. Теперь есть. А когда добавили scoped — так и вовсе вопрос стал решён даже лучше, чем в С++ (кое-чего мне и в плюсах не хватает, ес-но).
Введение статических методов у интерфейсов тоже неплохо, но это полумера.
По крайней мере, теперь можно избавиться от кучи фабрик на каждый чих, ведь теперь можно прописать абстрактный некий статический Create(args) у интерфейса.
Интересно, догадаются ли они добавить теперь в ограничениях генериков new(args) хотя бы для value-типов, т.е. where T : struct, new(args)? ))
Ведь технически это уже можно сделать без серьёзных доработок (в отличие от такой же фичи для where T : class)
Кодогенерация в процессе компиляции — тоже однозначно лайк.
Немного перемудрили с Рослином (были варианты чуть проще, вернее, можно было дать несколько альтернативных вариантов, где самый сложный был бы самым "общим", т.е. покрывающим все требуемые сценарии). Но один раз разобравшись и накидав своих повторно-используемых хелперов (вручную обыграв более простые сценарии), в принципе, жить можно.
Указатели на методы — ну вообще бомба.
Мы тут же родили легковесную библиотеку-замену делегатам на основе value-типов (включая ср-ва по частичному применению аргументов и прочего из функциональщины).
Видишь, вопрос не может и не должен ставиться "виртуальная машина"/"байт-коды" vs "нейтив".
Вопрос всегда должен быть о наличии тех или иных фич, в том числе объективно возможных или невозможных, из-за конфликта с другими фичами.
Помнишь я говорил лет 10 назад или больше, что хорошие оптимизации в дотнете принципиально невозможны из-за требований обеспечения доступа к объектам и вызова методов в т.ч. через рефлексию? Теперь ОАТ-компиляция убирает это противоречие через убирание доброй половины фич дотнета. ))
В режиме АОТ, если получаешь method handle и получаешь из него адрес метода (а сейчас по адерсу можно этот метод вызвать), то невозможна ситуация, когда делегат указывает на неоптимизированную версию метода, хотя рантайм уже породил оптимизированный его вариант.
V>>Но VM тут не при чём, такие же есть и нейтивные технологии, которые тоже разменивают производительность на подстраховку.
S>Да без проблем. Давайте, расскажите мне про эти нейтивные технологии. А лучше — не мне, а разработчикам CrowdStrike. А, и ещё авторам видеокодеков, а то Adobe Premiere до сих пор нет-нет, да и упадёт при редактировании видео. Где-то в недрах кодека у него NRE происходит.
Ты не знаешь таких языков что ле?
Или у тебя в нейтиве как в управляемых средах — очень сложно найти достаточно большой и известный программный продукт? ))
Да почти все продукты, которыми все пользуются — нейтивные.
Конкретно Adobe Premiere — это г-но мамонта из 90-х, контора давно испытывает не лучшие свои времена.
Например, MS Office с тех пор тотально переписали на плюсы за несколько подходов.
Голый сишный код — это ж как ассемблер.
Разумеется, плюсы тоже оставляют все эти опасные входы/выходы на манер либы Unsafe в дотнете, но при этом имеют абсолютно безопасные реализации тех же контейнеров, идиомы уникально или совместно владеемых объектов и т.д., а так же простые ср-ва реализации на библиотечном уровне любых идиом, в .т.ч. NotNull<> безо-всяких пенальти в рантайм.
Я ведь всё еще не о языках/платформах рассуждаю, как ты вечно пытаешься скатиться в эту сторону, я рассуждаю о людях, о подходах к разработке.
Я совершенно уверен (и не раз натыкался на собственном опыте), что никакие самые "безопасные" языки/среды не могут использоваться для отмазок расслабления булок.
В дотнете немного расслабить булки можно только если пользуешься совсем уж всем готовым и оперируешь совсем малым кол-вом приёмов/паттернов.
Но это можно сказать о любой технологии, управляемой или нет.
V>>Ты ведь не вникал, как компиляторы обслуживают потенциальные UB?
S>Конечно же вникал. У нас тут как раз курс лекций читался на эту тему — я походил, послушал
Теперь вопрос на засыпку — считал ли компилятор, что у него там UB или нет?
(в твоём примере)
V>>А на деле происходит обратное — компилятор предполагает, что никакого UB нет.
S>Нет.
А на деле да.
Компилятор этот момент даже не заметил — для него это обычный код.
Кое-какие явные выверты я обнаруживал только когда подавал заведомый null при вызове метода объекта по указателю — тогда GCC и CLang вели себя весьма странно, в отличие от других компиляторов. Т.е., явно обходили потенциальное UB.
А твой метод был ничем не лучше и ничем не хуже любых других методов, где происходят вычисления.
Причём, мне даже в некоторых конфигурациях удалось добиться того, чтобы тело метода не выкидывалось (подавал туда не константу времени компиляции), а всё-равно ответ выдавал неверный для int в режиме x64 — как раз из-за того же, почему всегда выдавал неверный ответ для short в любой конфигурации — из-за промоушена типа (в давнном случае в регистрах). Похоже, компилятор посчитал это безопасным, не влияющим на семантику (для well-formed кода), ну и вот... Стандарт ему позволяет.
Ты бы мог потратить время на опробование всевозможных типов данных (у меня там сетка была по всем интегральным типам, входящим в стандарт) и по многим компиляторам и их ключах оптимизации.
V>>И у него есть такое право — из-за допущения расширения типов промежуточных значений.
S>Нет.
V>>Ну ты реально тогда считаешь компилятор "черным ящиком", и на этом основании мысленно приписываешь ему любые магические св-ва. ))
S>Нет, я как раз случайно знаю, как работает компилятор
Вот врун.
Какой именно из кучи их?
И что именно ты "знаешь"?
V>>В отличие от тебя, у меня достаточно богатый опыт в парсинге, синтаксическом и лексическом анализе, кодогенерации и оптимизации.
S>Вижу, что опыт этот — в основном воображаемый.
Опыт этот в альфа и бета оптимизации графов вычислений, в оптимизации кодирования состояний автоматов и т.д.
V>>Код открыт, иди изучай.
S>Отметим, что ссылки на стандарт по-прежнему нет. Ну, можете ссылку на код с if-else мне показать.
Ну ты же "случайно знаешь", и?
Тебе даже не требуется мне ничего показывать (я не склонен манипулировать давлением на оппонента) — тебе достаточно было бы схематичного объяснения твоих представлений.
Но их никогда не было и не будет.
А те предположения, что ты выдвигал до моего появления в топике — это тебя просто несло.
К тому же, описания полного представления о происходящем так и не было.
(плюс я делал замечания насчёт возможного различного представления знаковых чисел, в некоторых из которых бывает +0 и -0, т.е. критиковал сам способ "решения" задачи is_max)
V>>А светить конторы, в которых работаем, в нашей области не принято из-за другого — процветающего HH на уровне хождения на грани порядочности.
S>Не переживайте, HH вам не грозит.
До СВО заваливали каждый месяц и без прямого засвечивания. ))
Сейчас чуть реже, в этом году не более десятка предложений накопилось.
И вообще, складывается ощущение, что с каждым годом всё больше потребность в тех, кто умеет выжимать из компов и сетей производительность.
Хорошо видно, что пошёл мощный откат после идиотизма нулевых.
S>>>За истекшее время можно было сходить и найти соответствующий пункт стандарта. Заодно понять, почему он неприменим к рассматриваемому примеру.
V>>Ты про плавучку? ))
S>Нет, я про int256.
Это не стандартный тип.
А если сделать его библиотечным — магия не сработает. ))
V>>Т.е. ты не знал, что есть фаза оптимизации при конечной кодогенерации?
S>Естественно знал.
Естественно знал, но как обычно в пыу спора забыл.
Потому что не о том думаешь. ))
V>>И что эта фаза чуть ли не основная по эффективности сегодня?
S>Нет, она там в последнюю очередь
В последнюю очередь чего?
Эта фаза на сегодня даёт львиную долю прироста эффективности.
Это почему мы свои продукты распространяем в статических либах в основном, чтобы дать возможность поработать LTO у клиентов.
V>>Семантические, это, надо понимать, альфа, бета и эта-преобразования? ))
S>Я же вам говорил — разработчики компиляторов этими терминами не пользуются.
Это ты этими терминами не пользуешься.
Или ими не пользовались в просветительских лекциях про компиляторы, на которые ты ходил "послушать", бгг...
Ну конечно, пользуются.
Просто эти термины предполагают некий обязательный бэкграунд для слушателей таких лекций, поэтому с вами могли общаться более приземлёнными терминами — "распространение констант", "преобразования, сохраняющие эквивалентность/семантику" и т.д. ))
И ты уже показывал, что не в курсе, что любые преобразования вычислений, сохраняющие семантику, кроме кеширований значений и перестановок инструкций в императивном коде (оба этих приёма зависят от побочных эфектов), описываются указанными преобразованиями из лямбда-исчисления.
Других в природе не существует.
Замена вызова ф-ии на константу-ответ (с чем ты столкнулся) — это простая бета-редукция.
Введение в C++ constexpr для функций-методов-объектов — это как раз для расширения этой стадии оптимизации.
S>Вы опять выдаёте себя с головой — нет у вас никакого опыта в "парсинге, синтаксическом и лексическом анализе, кодогенерации и оптимизации". В лучшем случае в ВУЗе 30 лет тому назад курсовик делали с разбором Паскаля.
Это тебе так бы хотелось, чтобы самому не выглядеть нубом?
Мне упражняться приходится регулярно.
И вот очередной кодогенератор из DSL приходится пилить, кстате, бгг...
В любом случае, все эти годы ты показывал примерно нулевые знания по теме построения компиляторов, по теме лексического и синтаксичекого анализа, по теме преобразования вычислений, а тут вдруг решил понадувать щеки?
А что произошло?
За ночь подтянул пробелы в образовании? ))
V>>__int256 пока что не стандартный тип, тикетов и багов в компиляторах, его поддерживающих, пока хватает.
S>Ну, пусть будет int128
Ну вот у меня в некоторых конфигурациях твоя магия на int128 не работала, хотя работала на int32 и int64.
Я же говорю — ты делаешь слишком дофига допущений/додумываний, вместо честного исследования вопроса.
V>>Вот когда все компиляторы подтянутся, тогда этот тип войдёт в стандарт, а пока что это попытка убежать. ))
S>Не убежите вы никуда. Компилятор все типы обрабатывает одинаково — потыкайте палочкой да убедитесь.
Вернись в то обсуждение и освежи — я показывал разное поведение для разных типов.
S>Особенности возникают только с типами short и signed char — потому, что для них в стандарте оговорены integral promotions.
Я показывал результаты уже после внесения необходимых исправлений в твой код с целью нивелирования этого
явного эффекта.
Обнаружил, что для некоторых типов он остался неявным, бгг...
S>И сохранение в память тоже не имеет никакого отношения — если так получилось, что на целевом процессоре нет int32 операции, то кодогенератор, естественно, сгенерирует код для int64. Но потом он обрежет результат — даже если этот результат промежуточный, и в память напрямую он никогда не попадёт.
Это ты сейчас цитируешь меня, если что. ))
Но это не относится к промежуточным вычислениям — для них нет такого ограничения.
И тем более это не относится к вычислениям, выполняемым в compile-time — ведь там речь шла о бета-редукции.
Т.е. компиляторам позволялось следующее:
— подставить значение и прогнать его через тело метода, т.е. провести compile-time интерпретацию происходящего, т.е. выполнить β-редукцию; в целочисленных вычислениях, учитывая "тупую обрезку результата" при сохранении его в память, это можно делать на максимально широком типе данных, например на int64 — и получишь описанный эффект;
— выполнить стандартные "символьные" η-преобразования, где x+1<x заменяется сразу на ответ.
S>И эзотерика тут ни при чём — обычная инженерная логика.
Да я давно понял, что ты продаёшь свои собственные представления, хосподя.
И не только я, судя по обсуждениям примерно 15+ летней давности.
Просто с тобой уже никто не общается — не заметил разве?
Ты ж постоянно перегибаешь в своей упоротости.
Ты ж не умеешь спорить — тебя никогда не интересует, собсно, предмет спора, никогда не интересует поиск истины/информации.
Тебя интересует поразвлечься-покрасоваться.
В 40+ это порядком в собеседнике утомляет, ес-но.
S>Нет, так не работает. Если бы компилятор произвольно расширял сложение, скажем, int64 до __int128, то тогда у нас бы (a+b)/2 работало корректно. Но ведь нет — вы не найдёте компилятора, который бы вам расширил аргументы, сложил, поделил, и потом сузил.
Хахаха, в голос просто! ))
Вообще-то, подобные операции есть в некоторых компиляторах над некоторыми архитектурами.
И деление с остатком туда же, и расширение результата вдвое при целочисленном умножении (например, до 128 бит, хотя все регистры 64-битные) и т.д.
Эти вещи специфичные для связки компилятора-проца и в спецификациях отдельно оговариваются.
Другое дело, что требовать этого в стандарте нельзя, но можно не запрещать.
Поисследуй эту тему в процах и компиляторах, там интересно.
S>Как вы думаете, почему?
Потому что ты никогда не задавался этим вопросом?
Потому что вырос на виндах и интел-совместимой архитектуре, и теперь натягиваешь эту сову везде, где дотянешься? ))
V>>А ты подтвердить свои рассуждения ничем не можешь, заметь, только позицией "А баба Яга против!"
S>Могу подтвердить ссылкой на стандарт.
Не сможешь.
Никакого одного пунтка, описывающего то поведение, не существует.
Это комплекс работающих совместно эффектов.
S>Но сейчас — ваша очередь.
Выложить тебе на блюдечке весь этот комплекс причин?
V>>Но озвучить эти причины, показав хотя бы схематически рассуждения компилятора, ты не в состоянии, верно? ))
S>Я схематически их уже озвучивал.
На мой манер, чтобы не допускать неоднозначных толкований — нет.
И я уверен, что ты специально бегаешь, дабы у тебя были пути отступления в твоём стиле "вы просто неправильно меня поняли", бгг...
Маленькая подсказка — ты в своих тех рассуждениях (в подветке про x+1<x) переборщил с обобщениями.
А так же упустил ретроспективу — почему одни вещи стали допустимыми, а другие нет.
Стандарт ведь не просто так развивался — на каждый чих было очень много и долго обсуждений и опыта в реальных проектах.
Это тебе не стандарты C#, которые стали более-менее обсуждаться только ближе к .Net Core 3.1.
Я ведь хорошо вижу, что обсуждение фич дотнета и компилятора C# всё больше скатывается к тому, как это происходило примерно с конца 90-х в С++.
Именно поэтому я ПРЕДПОЛАГАЮ, что и результаты будут весьма похожими.
Тем более, что похожие результаты уже есть — взять хотя бы сворованные read-only методы структур или ref readonly in/return.
Эти вещи тащят прямиком из плюсов, это const this и const Type &.
Зачем?
Ну я тебе пару раз объяснял-объяснял... тяжело с тобой.
Ну хоть разработчикам дотнета сейчас ничего объяснять не надо — понимают с полутыка.
Предпоследние разы когда репортил 4 года назад — всё было как-то сложно, долго, закрыто.
Последние два раза в позапрошлом году — уже совсем другое кино!
Резко вышли на общение, ПРЕДМЕТНО и эффективно обсудили, взял форк, внёс исправления, их тут же оперативно рассмотрели...
Дали ссылку на обновленную версию потом (чисто жест вежливости) в т.ч. на обновления в документации MSDN (ms-learn сейчас).
Та блин!
А раньше так нельзя было что ле? ))
Когда рапортовал в нулевых про баг в драйвере MS SQL Compact, то в какой-то момент хотелось уже просто послать, бо все входы-выходы дал, а с кем общался — задалбывал на твой манер: "а точно? а не показалось?" — и я должен был подробно расписать ему происходящее через Рефлектор... дурдом какой-то. У них-то исходники, а у меня нет!
Ну я тогда сильно разочаровался в этих дуриках-программерах из MS.
В моем мире такое бараньё не выжило бы, конечно, — быстро бы пошли на воздух всем стадом, бгг...
У меня тогда сложилось стойкое ощущение, что многое в дотнете делается по "остаточному принципу".
Поэтому, открыть исходники дотнета и привлечь сообщество к разработке — это выглядело верным решениям, если сами не тянут с должным качеством (читай — вложениями ресурсов/денег)
Поэтому, Синклер, не в технологиях дело.
Дело в подходе к разработке и только в этом.
И еще в непременном перфекционизме, который без той самой инженерной честности невозможен принципиально.
Враньё себе ведёт к лени ума.
Кстате, на старости это особенно вредно, бо ухудшает когнитивные способности.
Т.е., черты характера способны как продлевать, так и укорачивать жизнь. ))