К основному контенту

На хабре опять обострение у дошколят




Манипуляция №1

Все что выше будет давать неопределенное поведение из-за signed overflow.

Всё дело в том, что любые отсылки на стандарт С++, на какие-то отдельные реализации, на какие-то компиляторы - не состоятельны по определению. У раста нету никакого стандарта, а его поведение определяется одной единственной реализацией.

По это причине, при сравнении с C++ всё отметается сразу. Ведь если стандарт и множество реализаций, как и обратная совместимость нужны - раста не существует. Если раст существует - всё это ненужно.

Манипуляция №2

Я бы почитал, какие оптимизации не умеет Rust, особенно с учётом того, что в основе Rust лежит LLVM — тот же самый бэкенд, что и у Clang.

Невежество и враньё - вот две базовые составляющие последователей данного творения. В рамках базовой терминологии llvm ни в каком месте не является "бэкенд".

И это в описание того же clang чётко написано:

The Clang project provides a language front-end and tooling infrastructure for languages in the C language family (C, C++, Objective C/C++, OpenCL, CUDA, and RenderScript) for the LLVM project.

Но почему же последователи данного учения придумали какую-то свою терминологию? А я отвечу. Дело в том, что им необходимо поддерживать миф о том, что rust является самодостаточным и то, что какие-то свойства взятые на флаг пропагандой - никакого отношения к нему не имеют.

Скажу даже больше. В рамках базовых понятий rustc даже фронтендом не является. Он является частью фронтенда, потому как не способен сам генерировать llvm-ir.

Соответственно, Rust «бесплатно» получил

Не совсем бесплатно. Он получил это за счёт усложнения жизни своим последователям, а так же практически поставил крест на каком-либо развитии языка.

и разделяет с C++ большую часть независящих от языка трансформаций кода и оптимизаций.

Не разделяет. llvm создан для clang и clang существует в рамках llvm. К тому же, здесь говориться о каких-то "независящих" будто бы есть иные, но их нет, а всё что есть - имеет ничтожное влияние.

И хотя в представленном примере мы и получили одинаковый ассемблер, на самом деле, это случайность.

Это не случайность. llvm создавался под clang под c-family и в нём нету почти ничего, что не было бы доступно clang. А вот с растом такое не работает.

Проблема здесь следующая. clang(C++) по отношению к llvm первичны, а раст вторичен. Банальный пример приводит сам последователь, когда он просит llvm сделать то, что ему нужно, а llvm всё равно.

И так будет всегда. llvm будет делать что угодно, что нужно С++. С++ может делать что угодно, что ему нужно не взирая на то - умеет это llvm, либо нет. Если не умеет - научится. Раст же будет делать то и так как в llvm и никаким образом не может на него влиять. Может там спустя пару лет с барского плеча что-то сделают, но это максимум.

Таким образом раст не может развиваться как язык. Он не существует как язык. Вся семантика в нём - llvm. И если кто-то начнёт рассказывать про какие-то пародии на llvm на расте - это ничего не значит. Во-первых они почти полностью повторяют семантику llvm, о чём явно пишут. Во-вторых они несостоятельны целиком и полностью. В противном случае они бы использовались по умолчанию. И самое важное - их не было и нет сейчас. Поэтому раст как зависел от llvm так и зависит. Как не мог влиять на него - так и не может.

Хитрые оптимизации и наличие неопределённого поведения при переполнении знакового в языке C++ могут приводить к веселью и порой порождают такие статьи. Рассмотрим эту статью подробнее.

В статье ссылка на gcc - они тут же умножается на ноль. Ссылка на "уб" так же. Мы не можем сравнивать тёплое и мягкое. И если в одном случае мы говорим об одной реализации и её свойствах - мы должны говорить об этом и во втором случае.

Поэтому все сравнения должны вестись в рамках rustc и его поведение vs clang и его поведение.

Как видите, документированное поведение и отсутствие неопределённого поведения при переполнении знакового действительно делают жизнь легче.

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

И автор загнал себя в ловушку. Либо С++ быстрее, либо никакого уб нет.

Здесь мы наблюдаем бесконечную рекурсию. Опять-таки код компилируется в одинаковый ассемблерный выхлоп, то есть NOP для функции bar как в C++, так и в Rust. Но это баг LLVM.

В очередной раз последователь ссылается на llvm. Попытка не состоятельно без признания последователем зависимости от llvm и отсутствия влияния на него.

При переполнении C++ прыгает на инструкцию ud2, которая приводит к "Illegal instruction (core dumped)", а Rust прыгает на вызов функции core::panicking::panic, подготовка к которой занимает половину ассемблерного кода. В случае переполнения core::panicking::panic дает нам красивое объяснение падения:

Полностью несостоятельные рассуждения. Кто-то просил красивости? Нет. Этот мусор валяется в теле функции с высокой долей вероятности будет загаживать кеш процессора. И данные и инструкции в кеше не лежат по одной.

Так откуда взялись эти "лишние" инструкции, которые трогают память?

Абсолютно неважно откуда они взялись. Они есть.

И C++, и Rust сгенерировали одинаковый выхлоп ассемблера, оба добавили push rbx для выравнивания стека. Q.E.D.

А здесь уже откровенное враньё. Каким образом левый придуманный пример отменяет различия в изначальном примере? То, что на С++ можно добиться подобного поведения ничего не означением и никак претензию не снимает.

К тому же -ftrapv в gcc сломан с 2008 года.

Опять же - попытка не состоятельна. Мы не рассматриваем gcc. Если мы рассматриваем и гцц, то для раста мы рассматриваем и альтернативные компиляторы. Правда лучше этого не делать, потому раст тут же поломается.

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

Да, в данном случае это так. Здесь даже в рамках одной функции 3 потока параллельного чтения + alu-операции. У этого кода очень высокий ipc и кол-во инструкций тут имеет значение. К тому же непонятно что будет с этой записью.

И чтобы хоть как-то приблизиться к ассемблерному выхлопу кода на сырых указателях ему приходится добавлять noexcept, rvalue ссылки

Никакой noexcept здесь ни на что не влияет, как и rvalue. Объект обязана создавать вызывающая сторона. Если автор не хочет его создавать - он использует ссылки. Ссылки в С++ не требуют писать лишнего мусора, как в расте. И в данном случае никакое rvalue не нужно - оно ничего не значит. С таким же успехом автор мог передать и через обычную ссылку. И никакой move тут ничего не делает.

и использовать std::move

И опять враньё. Никакой раст не освобождает от move - просто там move по умолчанию. Когда как в С++ нет. С таким же успехом можно кричать почему тут mut ptr mut, а в С++ такого нет.

К тому же это не более чем фокус. В расте drop прикручен с боку и не является аналогом крестовых деструкторов. Этот фокус работает только с Box, если взять что-то где drop прикрученный сверху не сработает - будет всё тоже самое, даже хуже. Потому как в С++ есть средства для оптимизаций, а в расте их нет. Единственное, что есть - unsafe.

При меньших трудозатратах Rust генерирует меньше ассемблера.

Тут автор путается в показаниях. То меньше ассемблера ничего не значит, то уже значит.

В декабре 2019 Rust превосходил по производительности C++ согласно результатам Benchmarks Game.

Даже знаю почему - это сделал я. Я позволил расту что-то там превосходить. Вот ведь какая незадача. И даже расскажу как это было. Я пришел и полностью уничтожил раст. После адепты раста подсуетились, поменяли задним числом правила и выпилили и моё и множество других C++-решений.

Но на таких синтетических бенчмарках языки будут раз за разом обходить друг друга. Я бы не отказался посмотреть нормальные бенчмарки.

Никакого обходить не было и не будет никогда. Хорошо, я сыграю в эту игру, снова.

К счастью,

К сожалению. Это не более чем помойка, как и любой пакетный менеджер. Ещё не уровень leftpad, но уже скоро.

у языка Rust есть пакетный менеджер cargo,

У C++ их десять штук.

который позволяет один раз сгенерировать объявления и поделиться ими со всем миром.

Это ничего не значит. Необходимости писать и обновлять обёртки это никак отменяет.

Как вы понимаете, люди делятся не только сырыми объявлениями, но и безопасными и идиоматичными обёртками.

Опять же, рядовые лозунги. На каком основании они безопасны и идиоматичны? Это как с actix-web? К тому же

На 2020 год в реестре пакетов crates.io находится около 40 000 крейтов.

99% из которого мусор, либо огрызки других либ. Сколько там библиотек уровня си?

Пример с flate2 примечателен тем, что в начале своего существования этот крейт использовал сишную библиотеку miniz, написанную на C, но со временем сообщество переписало сишный код на Rust. И flate2 стал работать быстрее.

Это всё нужно знать о сообществе. От сишных либ он так и не избавился. Ссылок на бенчмарки нам не предоставлено. Уровень переписали MINIz - это сильно. Всё переписали свелось к банальной перепасте 1в1.

К тому же, нас опять обманули:

test miniz::compress_bin_lvl_1          ... bench:   1,247,595 ns/iter (+/- 49,416)
test miniz::compress_bin_lvl_6          ... bench:   7,376,442 ns/iter (+/- 126,005)
test miniz::compress_bin_lvl_9          ... bench:  17,385,602 ns/iter (+/- 202,425)
test oxide::compress_bin_lvl_1          ... bench:   1,463,559 ns/iter (+/- 676,616)
test oxide::compress_bin_lvl_6          ... bench:   7,636,131 ns/iter (+/- 111,567)
test oxide::compress_bin_lvl_9          ... bench:  17,646,887 ns/iter (+/- 248,669)

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

Увы, мнение об отключении всех проверок в unsafe — это типичное заблуждение, потому что в документации к языку Rust сказано, что unsafe позволяет:

Это попросту враньё. Уже не первый раз вижу как последователи данного учения бегают с этим, но unsafe именно отключает ВСЕ проверки.

Ни о каких отключениях всех проверок Rust здесь и речи не идет.

Говорит. В расте вообще никаких проверок нет. Поэтому всё что перечислено - это единственные проверки.

Если у вас ошибка с lifetime-ами, то просто добавление unsafe не поможет коду скомпилироваться.

Поможет, очевидно.

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

Нет, это враньё. Ссылка - нелепая пропаганда. Идём и смотрим:

    let mut x = 5;
    unsafe {
        let y = &mut x as *mut i32;
        let z = &mut x as *mut i32;

        println!("{}", *y);
    }

Ой, нас обманули. В конечном итоге статейка рассчитана на тех, кто не будет разбираться и верующих. Которые просто будет везде повторять заголовок.

Что же нам показали? Нам показали то, что ссылки работают в unsafe так же. И это полная чушь. В том и проблема, что так же. А зачем нам unsafe, если всё так же? Правильно - нахрен не ненужен. А то, что там так же работают ссылки - это не более чем фокус, повторю. Никто в рамках unsafe не будет использовать ссылки, потому как unsafe и существует для нарушения правил.

которые компилятор самостоятельно проверить не может.

Показания ещё раз поменялись. Дак может или нет? А если он итак может - зачем нужен unsafe? Нам нужно переназначить позицию ссылки, нам нужны две мутабельные ссылки. Это нужно везде и это никак не проверяется. От того раст с ног до головы обмазан unsafe, as_mut_ptr и прочими прелестями.

По статистике Microsoft, 70% уязвимостей связаны с нарушениями безопасности доступа к памяти и с другими классами ошибок, которые Rust предотвращает ещё на этапе компиляции. Это ошибки, которые физически невозможно совершить в безопасном подмножестве Rust.

Статика Microsoft всем интересна. Компания всегда славилась умением в С++ и в качество кода.

По поводу:

Rust предотвращает ещё на этапе компиляции

Это враньё. Ничего раст не предотвращает - это сказки для бедных. Раст это такой примитивный язык с прикрученным борроу-чекером. Он тоже крайне примитивный.

Может он только в рамках текущего контекста найти все алиасы. Причём он их даже не ищет. Каждый адепт этого языка обязан руками описывать все связи между алиасами. Там в некоторых примитивных случаях есть расстановка по умолчанию, но это не более чем расстановка. Это никак не выводится и если поведение отличается от дефолтного, пусть и примитивно - руками писать нужно.

И весь борроу-чекер сводится к подсчёту ссылок в текущем контексте. Если ссылка одна - объект можно мутировать. Если более одной - нет.

Более ничего этот супер-язык не умеет. Всё остальное, что вам рассказывают и показывают - фокусы. Которые не работают в рамках языка. Они работают лишь в рамках api, примитивного api данного стандартной библиотекой. И это всё api, о чудо, построено на хаках.

Таким образом никаких гарантий раст не даёт. Он что-то даёт только в рамках примитивного api с примитивными же возможностями. Даже для своей stdlib он никаких гарантий не даёт.

Но особенностью Rust является возможность разграничения кода на безопасный и потенциально опасный с последующей инкапсуляцией последнего. А если на текущем уровне гарантировать корректность семантики не удаётся, то unsafe надо делегировать вызывающему коду.

Это враньё. Любой язык позволяет разграничить безопасный и опасный код. Последователь данного учения врёт. Единственное, что работает для раста - это возможность ЯВНО разграничить.

Но это, как можно догадаться, полная чушь. Потому как если код системный - там будет unsafe через unsafe как в stdlib раста. Причём нужно понимать, что stdlib раста - это тормозное, примитивное поделие. Оно зависит от libc на си, от аллокатора на си.

Основного системного хардкора там даже нет. Там ничего нет. Но не смотря на это - unsafe через unsafe. Такие дела.

И эта безопасная версия никогда не выстрелит по памяти, какие бы аргументы вы туда не передали.

Как и vector::at, но из этого ничего не следует. Здесь последователь врёт. Из того, что функция не помечена unsafe никак не следует то, что она куда-то там не стрельнёт. Ошибись адепт в проверке и она ой как стрельнёт.

В конечном итоге разница крайне сомнительна. Никаких гарантий safe-функции не дают. Наоборот - они даёт обманчивую гарантию. Это как взять в кишки чистой функции засунуть сайд-эффекты и сказать "ну их же не видно в интерфейсе".

Но это неверный подход. Нельзя прятать потенциальные ошибки. Здесь пропаганда врёт. unsafe должен отравлять функцию, которая его использует. Потому как любая функция, которая его использует - не безопасна. Как и та функция, которая её использует и так далее.

Получается, что очень сложно придумать в чём вообще преимущество.

Я выложил проект с флагами компилятора на гитхаб. Результирующий выхлоп ассемблера аналогичен коду, написанному на чистом C(link:godbolt), но имеет гарантии кода, написанного на Rust.

Никаких гарантий эта портянка не имеет, очевидно. Это настолько нелепая чушь. Кстати, если заменить u32 на i32 в функции с гарантиями раста появится ub.

Вы не знали? Это сила гарантий. Ну бывает.

В 2018 году доказали, что система типов Rust, механизмы заимствования, владения, времён жизни и многопоточности корректны.

Эти доказательства не имеют смысла, потому как там доказывать там нечего. Там нет никакого владения, времени жизни, многопоточности и прочей херни. Что там есть я описал выше - всё остальное следствия.

К тому же всеми этими доказательствами можно только подтереться. Во-первых система типов не постоянна. Того api, что вчера не было - завтра будет. Во-вторых все доказательства существуют в рамках какой-то модели. И никаких нет доказательств тому, что используемая модель корректна.

Тоже самое касается реализации. Не существует доказательств корректности реализации.

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

Эта ахинея никак не может следовать из указанного выше. В конечном итоге эту чушь можно свести к следующему "если всё работает так как мы вам обещаем - всё будет работать". Но это так не работает. Никто не проверял корректность каждого api и его реализации. А значит оно не может являться корректным.

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

Опять же - какие-то лозунги уровня "правильные обёртки". И тут адепт путается в показаниях. Дак правильность обёрток зависит от оборачивающих, либо раст гарантирует? Нужно определиться с показаниями.

В конечном итоге в реальности мы имеем следующие. Обёртка может быть и скорее всего является дырявой. Там раст ничего не гарантирует. Сишный код может быть дырявым - там раст ничего не гарантирует. Всё сводится к вере в то, что и сишный код и обёртки правильны. Причём язык это никак не проверит.

В качестве практического применения своей модели авторы доказали корректность некоторых примитивов стандартной библиотеки, включая Mutex, RwLock, thread::spawn. А они используют сишные функции. Таким образом, в Rust невозможно случайно расшарить переменную между потоков без примитивов синхронизации; а, используя Mutex из стандартной библиотеки, доступ к переменной всегда будет корректен, несмотря на то, что их реализация опирается на сишные функции. Круто? Круто.

Нелепый набор лозунгов. Если что-то использует сишные функции - оно уже дырявое. Потому как вспоминает лозунги про 70%.

Далее, здесь адепт вас в очередной раз пытается обмануть. Всё это чушь никак не связана с мутексами, локами и прочей хернёй. Всё это связано с банальностью - по умолчанию нельзя пошарить данные. А значит нельзя поменять данные из двух мест. mutex тут не причём.

Но теперь я открою тайну, почему все эти рассуждения несостоятельны. Во-первых mutex"ы - это какой там 95 год? Они уже почти везде целиком и полностью неюзабельны. Но супер-передовой язык наконец-то научился в них.

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

Вот люди идиоты. Десятки лет код пишут, а теперь пришли гении и сказали "если не шарить - проблем не будет". Да вы что. А мы то не знали.

Комментарии

  1. ```
    В качестве практического применения своей модели авторы доказали корректность некоторых примитивов стандартной библиотеки, включая Mutex, RwLock, thread::spawn. А они используют сишные функции. Таким образом, в Rust невозможно случайно расшарить переменную между потоков без примитивов синхронизации; а, используя Mutex из стандартной библиотеки, доступ к переменной всегда будет корректен, несмотря на то, что их реализация опирается на сишные функции. Круто? Круто.
    ```

    Удалил конструктор копирования и получил в плюсах тоже самое, с проверкой на этапе компиляции.

    ОтветитьУдалить
    Ответы
    1. Не, это так не сработает. Вернее, конечно же, работает. Но сектанты с этим не согласны. В общем смысл в том, что проблема не в самом локе и его копировании.

      Дело в том, что у сектантов можно связать время жизни лока и ссылки, которую ты из под него получаешь. Таким образом ты не сможешь вывести эту ссылку за скоуп.

      Но во многом это подлог, потому как на самом деле ссылки в этой поделке - указатели. В крестах же ссылки другие и там в принципе ненельзя вывести ссылку за скоуп. https://godbolt.org/z/Zzr9iR - вот я тут подробней объяснил.

      Всё это у сектантов работает крайне примитивно. Их просто обязали везде и всюду прописывать алиасы руками, запретили указатели. Что-то подобное бахают тут: https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Lifetime.pdf

      Удалить
    2. Этот комментарий был удален автором.

      Удалить
  2. На какой пост ты отвечаешь? Ссылку-то оставь.

    ОтветитьУдалить
  3. Какая же паства Царя тупая - не могут загуглить по цитатам и найти источник.

    ОтветитьУдалить
    Ответы
    1. Какой же тупой петух-анонизмус, не понимает, что есть элементарные нормы оформления статей.

      Удалить
    2. Причем тут нормы статей, когда ты, тупая мразь, спрашиваешь ссылку на статью, которую он комментирует?

      Удалить
    3. Давай, петушок, докопайся до орфографии.

      Удалить
    4. У Царя не паства, а свита, дурачок.

      Удалить
  4. видели, что растоман там ответил в комментах про signed integer overflow? "Уточнил почему Rust не выполняет эту оптимизацию: потому что она некорректна".

    Он УТОЧНИЛ. Понятно, да? Я думаю, они специально высирают как можно более дикую чушь, чтобы спровоцировать несектантов и побежать стучать модераторам. Потому что а как еще бороться с тем, что их тыкают носом во вранье и незнание элементарных вещей?

    ОтветитьУдалить
    Ответы
    1. Нужно понимать, что все эти адетпы - это бездарный сброд. Это опущенцы-неудачники, которые пытаются хайпить и найти себе хорошего хозяина, который будет их кормить. Это обычные шлюхи панельные - здесь нечему удивляться и ловить их на вранье.

      А так методичка там одна на всех. Всё чего нет - ненужно. Всё некорректно. К тому же, в основном у них нет достаточно сильных оппонентов. Все занятые люди заняты, а пару случайных людей можно и заминусовать. У мразей есть ручки.

      Самое интересное тут то "говнораст не выполняет эту оптимизацию". В этой потуге весь смысл. Она само по себе настолько нелепа, что непонятно как вообще подобные бездарности могут существовать. Насколько же уровень ЦА низок, что никакого массового противодействия среди сектантов подобному нет.

      Скоро зададут вопрос заданный мною. Сектант показывал пример с вызовом сишки и показывал, что всё безопасно. Но на самом деле там УБ. И он специально скрыл его другими типами, потому что знает - за вранье не поймают.

      Не ничего. Если у меня хватит времени/мотивации я кое что доделаю. Посмотрим что из этого выйдет.

      Удалить
  5. про раст, отсюдава (https://habr.com/ru/post/504622/)
    >Львиная доля сложности языка как раз состоит в понимании исключений и частных ограничений языка, которые сама концепция, кажется, иметь не должна.

    ОтветитьУдалить

Отправить комментарий