Как мы ржавели. История внедрения и обучения

    Все говорили – переходи на rust! Начинай пользоваться самым-самым языком, который самый любимый язык на stackoverflow и всё такое.

    Я тяжело вздохнул и огляделся. Ну опять двадцать-пять. Ладно, давайте разбираться, как правильно покрывать всё ржавчиной.

    Профессионально я программирую уже 17 лет. В далёкие-предалёкие времена я начал изучать программирование с x86 Assembly. Такой жестокий подход к изучению компьютера дал мне глубокое понимание того как работает процессор и что делают другие языки программирования. Учить новые языки для меня никогда не было проблемой. Я их просто учил. C, C++, шарпы, ГО, тысячи разных скриптов и фреймворков. Чего уж там, ещё один язык, можно и выучить.

    Ага. Только вот не с этой ржавой развалюхой. Я просидел две недели над официальным руководством, пялился в VSCode и не мог выдавить из себя больше чем fn main() {}. Ну какого же чёрта?

    Я просто закрыл глаза, открыл руководство на рандомной странице и начал его читать. И прикол в том, что я понял о чём там говорится. И тут до меня дошло… Руководство написано наизнанку. Начало и конец ничуть не лучше чем в Мементо Кристофера Нолана. Они как-то умудрились запутать в общем-то нормальное руководство.

    После этого всё пошло получше. Ржавые шестерёнки заскрипели и начали крутиться. Программа пошла-поехала. Если хотите знать как я внедрил rust в продакшен, как я ему научился и что из этого вышло – добро пожаловать под кат. Реальные люди, коммиты, примеры и никаких todo-list и хеллоу-ворлдов. Ржаветь так ржаветь.

    Для начала – быстро расскажу что я заменил на rust. Жил да был лаборант. Ему сказали, мол, напиши программку – подключается вот к этой системе, сгружает бинарные данные по сети с порта, конвертирует их в удобочитаемый формат и сохраняет всё в базу данных. Лаборант был очень любознательным выскочкой. Почему-бы не показать себя? Он и показал. Написал программу на C# которая подключалась к серверу и тянула данные с компьютера. Преобразовывала их в JSON, который был доступен через POST API. С шарпами он был не очень дружен, посему сохранять в базу данных всё решил на Node.js, который эту программу на шарпах дёргал, получал JSON, делал немного логики и гнал в базу данных (postgres). На всё это дело был прикручен веб интерфейс, который позволял крутить настройки. Всё бы хорошо, но поиска по полученным данным у нас не было. Лаборант сказал: «Да не вопрос! Щас всё сделаю!» и поставил на всё это дело Elasticsearch. Поддерживать всё это дело стало страшно, посему лаборант сказал: «Щас всё починю!» и написал кучу Doсker файлов, положил всё в контейнеры, сделал docker-compose и всё заработало.

    Примерно через год я пришёл и посмотрел на всё это дело. Полный дамп базы данных весил 250Мб. Прирост данных составлял 50 метров в год. Чего там, тривиальная задача. Но всё это крутилось на выделенном сервере с 32 гигами оперативки и 24 процессорами. Сервер выл и жужжал потому что приходилось гнать 16 докер-контейнеров с кластером Elasticsearch, который постоянно рушился от перегрузки.

    Ай-я-яй. Подумал я. Надо что-то делать. Времени было достаточно, я и решил, почему-бы не попробовать rust?

    Акт номер 0: Вступление

    Конечно, есть видео на утубиках и всё такое, но я же пришёл из другой эры. Когда мы учили С++ нам в помощь приходила только свежая болванка с дампом MSDN. Мы любим нормальные доки.

    Ну и чтобы вы подумали? Доки есть. И они даже в очень приличной форме.

    The Rust Programming Language – замечательная книга, которая раскрывает все основные аспекты языка и показывает как им пользоваться. Книга примечательна тем, что сначала заводит вас в непроходимый омут с чертями, лешими и пресмыкающимися, а после пытается вас оттуда вытащить. (600 страниц)

    The Rust Reference – полное, доскональное и дотошное руководство, которое расскажет и покажет что делает каждая закорючка на экране. Хотите знать как rust разложит в памяти ваш замечательный enum? Вам сюда. Абсолютно человеко-нечитабельное руководство, которое рассказывает обо всём. (300 страниц)

    Rust Compiler Error Index – rust имеет замечательную фитчу. Ихний компилятор настолько разговорчив что вам даже не понадобится резиновая уточка для разговоров. Во время написаниия программы вы будете наслаждаться простынями всяких ошибок компилятора. Просто невероятное количество их. В этом замечательном томике все эти ошибки шибко расписанны и рассказаны. (400 страниц)

    Rustonomicon – каждый кто более-менее начал работать с rust будет вам рассказывать про «Номикон». Эта книга по чёрной магии, которая позволяет вам убивать ваших врагов и привораживать по кофейной гуще. Все страшные стороны работы rust раскрыты именно здесь. (200 страниц)

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

    Акт номер 1: О чём вы, Морфеус?

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

    Но давайте посмотрим на мир более серьёзно, почему же всё-таки rust? Код, генерируемый rust использует LLVM как компилятор. Что это нам даёт? В общем-то неплохую переносимость на разные платформы, при полном отсутствии потребности в разных фреймворках. Программа на rust будет практически такой-же быстрой, как и программа на Си. Конечно куча флейм-троллей сейчас может начать комментить в стиле холивара «Раст против С» и наоборот, но чёрт бы с ними.

    Какая разница если rust такой же быстрый как Си или если Си его обгоняет на 5%? Забейте. Не вникайте в это. Момент в том, что rust это системный язык программирования, который позволяет работать с вашим железом на очень низком уровне и не содержит в себе миллионы абстракций, фреймворков и тому подобное.

    Давайте посмотрим вот на что:

    Проект написанный на .net core 3: Исполняемый файл – 6 Мегабайт.

    Проект написанный на rust: Исполняемый файл – 240 Килобайт.

    Хаха! Но эти цифры – подстава и обманка! Хреновые маркетологи.

    Я беру этот проект, копирую исполняемые файлы на флешку и запускаю их на другом компьютере (Windows 7).

    И что бы вы думали? .net core проект не запускается! Почему? Нет фреймворка.

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

    Результат? 89 Мегабайт!

    Хаха! Вот так тебе и надо, .net! Хитрец! Пытался меня обмануть!

    Ладно, теперь запускаем наш проект на rust. Вот, смотрите, просто кликаешь сюда и…

    The program can't start because VCRUNTIME140.dll is missing from your computer. Try reinstalling the program to fix this problem.

    Ладно, пересобираем проект и вшиваем все зависимости в исполняемый файл и… 569 Килобайт.

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

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

    Акт номер 2: Учиться, учиться и ещё раз учиться

    Вот вам пример. На странице 38 официального руководства (600 страниц) показан простой код вот этой замечательной программы:

    Программа просто замечательная. Игра «отгадай число». Компьютер загадывает число, а ты его сидишь и отгадываешь. Тривиально, Ватсон, не так ли?

    Нет.

    Ничегошеньки не тривиально. Эта «простая» программа для «новичков» перегружена подводными камнями, минами и противовертолётными бомбами.

    Прикол в том, что несмотря на всю свою сиобразность, rust включает в себя неимоверное количество синтаксического сахара, и всяких плюшек, которые компилируются в приличный и быстрый код. Все эти плюшки запутывают тебя до смерти, если в них не разобраться. И всё это тебе выдаётся на блюдечке с голубой каёмочкой, пока тебе говорят «Вот скушай наш ᾋﯓﻼ҉ᴪᾠﭥ», он вкусный.

    Нет, нет, нет и ещё раз нет!

    Первая глава этого руководства должна гореть в печи!

    Давайте я вам покажу как его читать.

    Начинать читать это руководство нужно с главы №4 под названием Understanding Ownership. Разбираемся в правилах владения переменными. Если вы начали работать с rust, то эти правила придётся учить и разбираться в них. Это именно то, почему и как rust такой замечательный.

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

    Но если нужно написать код, который двигается побыстрее, то, пожалуйста, заменяем сборщик мусора на ручное управление памятью. Мы в ассемблере так всегда и делали. Результат?

    Результат правильного управления памятью.
    Результат правильного управления памятью.

    Накосячить с памятью – это просто святое.

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

    Что делать? Либо вы отдаёте все в руки вашего фреймворка, который может быть неповоротливым и жрать кучу памяти, либо вы делаете всё в ручную, но это страшно.

    В rust всё это было решено следующим образом: Создали ссылку на новый объект – компилятор быстренько встроит туда код, который запросит память у системы, прочистит и инициализирует эту память. А после того, как ваша ссылка уходит за зоны видимости, то компилятор автоматически добавит код, который память по этой ссылке освободит и отдаст обратно системе.

    Всё просто и красиво. Чики-пуки! Ага.

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

    Пример:

    let s1 = String::from("hello");

    let s2 = s1;

    println!("{}, world!", s1);

    Простейший код, который понятен каждому программисту. Он нифига в rust не скомпилируется. Почему? Потому что при подобном присвоении существует возможность когда система освободит память дважды, что может привести к ошибке.

    Ладно, хватит вас пугать.

    Читаем главу Ownership и разбираемся как эта память работает. Благо, глава написана очень толково и рассказывает обо всём по порядку.

    Акт номер 3: Все по порядку

    После главы №4 надо прочитать главу №3.

    Удивительно, но у некоторых людей странное понимание слова «Номер». Они их путают местами.

    В главе №3 рассказывается об основных концептах языка. Как и с чем работать, как создавать переменные, ветвить программу и всё такое. Все эти данные на самом деле завязаны на понимание главы 4.

    Ладно, разобрались с азами. Теперь пройдитесь по главам 5 (Использование структур), 6 (Enum и паттерны), а затем, понятное дело, прочитайте главу 8 (Коллекции). Это даст вам понимание основных объектов и как с ними работать.

    После этого рекомендую перечитать главу №4. Открываются новые горизонты.

    Теперь можно смело переходить к главе №9 (Улаживание ошибок).

    В rust есть один прикол – в нём нет такого понятия как Null. Если вы погуглите “Null is a mistake” вы поймёте о чём я говорю. Приличное количество разработчиков ещё с 1965 года жалуются на то, что такое понятие как Null в значении переменной было неправильной идеей и не должно было существовать.

    Rust избавился от идеи Null и это приводит нас к очень интересной, приятной и понятной системе обработки ошибок. Единственное что – вы такую систему видели не часто, и её надо знать, если хочется работать в rust.

    Глава №7 рассказывает о том, как распилить программу на куски, чтобы не нужно было писать весь код в одном файле. Далее можно смело переходить к главе №10, и учить про дженерики, трейты и тому подобные финтифлюшки.

    После этого рекомендуется перечитать главу №4. Сознание расширяется.

    За главой 10 следуют главы 13 и 17. Они объясняют что rust имеет черты как функциональных так и объектно-ориентированных языков, и рассказывают о том, как пользоваться всеми этими прибамбасами.

    После всего этого можно переходить к двум самым зубодробильным главам в этой книге. 15 и 16. При прочтении этих глав рекомендуется перечитывать главу №4 после каждого абзаца. Почему? А всё потому что если вам пришлось долго разбираться в том, как происходит управление памятью в обычной программе, то понять управление памятью в многопоточных программах будет занятием для чемпионов.

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

    Ладно, после этого – вы в доме хозяин. Можно начинать перечитывать книгу с главы №1 и потом переходить к главе №2. Приведённая задачка на нахождение числа покажется вам просто детской игрушкой (коей она и является). После идите по всем остальным главам и вдумчиво читайте. После всего этого вы сможете писать на rust.

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

    1. Вы будете знать что на самом деле написано в Номиконе. (Хотя и лезть туда вы не будете).

    2. Вы сможете читать The Rust Reference.

    С этими знаниями вы на самом деле можете сесть и начать разрабатывать свой первый проект, который будет посложнее todo-list.

    Акт номер 4: Реальности

    Реальная разработка принесёт свои определённые знания.

    Опыт и мнения которыми я с вами поделюсь, являются чисто моими и у вас может сложиться другая картина восприятия мира.

    Первое, что вы поймёте – компилятор не прощает огромного количества ошибок. Да, конечно, это хорошо, ибо потом эти ошибки не пройдут в продакшн. Но и с другой стороны – собрать прототип на rust за пару минут не получится. Если вы где-то сказали «Тут должно быть число, но в 1% случаев его может не быть», то вам придётся писать эту ветку обработки 1% случаев. Код не скомпилируется.

    Те кто не освоил главу №4 будут играть в замечательную игру «Уломай компилятор скомпилировать твой код». Все правила управления памятью, которые делают rust таким мягким и пушистым, заставляют вас думать по другому об устройстве вашей программы. Никаких висячих хвостов или незаконченных кусков кода. Если вы просто пытаетесь написать программу от балды, то скорее всего вы потратите часы на то, чтобы привести её в порядок и скомпилировать.

    Далее идёт каталог программного обеспечения crates.io.

    Это сайт с которого можно слить приличное количество модулей и библиотек для вашего rust приложения. Сайт на самом деле содержит огромное количество программного кода. Но реальность не всегда замечательна.

    Например, мне пришлось потратить порядка 2‑х часов, чтобы найти нормальную библиотеку для работы с postgres. Всё было замечательно, и я работал с этой библиотекой порядка десяти часов, пока не наткнулся на очень интересную проблему. В rust нет встроенного типа для валютных операций. Float не подходит, нужно было что-то типа Decimal. Decimal мне удалось найти в виде библиотеки, которую я нехотя скачал и добавил в свой проект. И тут внезапно выясняется, что драйвер для posgresql понятия не имеет, как конвертировать этот Decimal в Postgres Decimal.

    Пришлось потратить 4 часа на разбирательства и написание конвертера.

    Далее, достаточно скверный момент в rust – документация к пакетам. Да, в rust есть встроенная система документирования кода, и ты всегда можешь слить доки которые авто-генерируются из комментариев к твоему коду. Но вот эти доки зачастую оставляют желать лучшего. Тот же Decimal, из примера чуть повыше, имеет замечательную документацию, в которой сказано следующее – «Это Decimal. Позволяет работать с Decimal. Работайте. Благослови вас Господь!»

    Пришлось лезть в исходники и копаться там, пока не разобрался, как же написать этот конвертер.

    С другой стороны, развитые проекты имеют хорошие сайты, на которых публикуется тонна дополнительной документации. Например, tokio, actix и rocket.rs. Эти проекты (вы обязательно о них услышите, как только достаточно проржавеете) предоставляют огромное количество дополнительного чтива.

    Акт номер 5: Итоги?

    Старый добрый дымящийся и ревущий сервер успокоился и перестал выходить из себя. 100-мегабайтное приложение на C# было заменено 564 килобайтами кода написанного на rust. 200 мегабайт памяти которые потребляло приложение на шарпах теперь превратились в 1.2 метра RAM для программы на rust. (Заодно избавился от двух докер-контейнеров в которых это приложение работало).

    После трёх недель изучения языка, мне потребовалось примерно неделя на то, чтобы переписать приложение. Ну, до кучи, я посмотрел на всё это дело, состоящие из докеров и yaml файлов, и начал его разбирать. Убрал оттуда Elasticsearch. Ко дну пошли семь докер-контейнеров. Как выяснилось, большинство поисков по данным было сделано следующим образом – пользователь выбирает даты в Elastic и после этого скачивает csv. Затем весь поиск происходит в Excel. Elastic был заменён простой командой в cli, которая позволила сливать csv по дате, благо это можно было делать и из postgres.

    Далее пришёл черёд web интерфейса для настроек. (Ещё пара контейнеров улетает в океан). Настроек оказалось порядка 12-ти и я их запихнул в TOML файл, который просто читается моим rust приложением. Ушёл ещё один докер-контейнер. Кит остался плавать один, без контейнеров. Он обиделся и уплыл восвояси. Докер можно было сносить.

    Я посмотрел на сервер. Остался только postgres и моё замечательное rust приложение. Слил всё это на raspberry Pi и показал всем чудеса оптимизации.

    В приведённом выше примере Rust был не единственной причиной почему серверы перестали визжать от перенапряжения. Дизайн приложения отсутствовал как класс. Всё было сделано наспех и безалаберно склеено докером, ибо так всё и должно быть. Я думаю, что если бы я полностью переписал всё на C#, то итоговое приложение получилось бы в 100 мегабайт и сидело бы себе, откушавши 250 мегабайт памяти.

    Просто это никак не сравнится с полуметром на диске и полутра-метрами оперативки. Я снова почувствовал себя так же хорошо как в детстве, когда я запускал свои приложения на ассемблере и видел, как какие-то 20 килобайт единичек и ноликов создавали поразительные визуальные эффекты на экране. Rust это весело. После того как прочитаешь их документацию.

    Акт номер Last: вывод

    Rust это годный язык программирования. Он не предназначен для прототипирования приложений. Разработать agile проект на rust за 20 минут не получится. Rust требует хорошего понимания системного программирования. И хотя rust и не такой сложный как Си в управлении памятью и ссылками, он требует очень аккуратного и правильно спланированного дизайна приложения, и, так же как и Си, не прощает ошибки. Но в отличие от Си, очень многие из этих ошибок будут не прощены на этапе компиляции, ещё до того как ваше приложение пойдёт в продакшен.

    Использовать rust в изолированных проектах? Да! Если знаете как.

    Заменить простую системную утилиту, которую какой-то лаборант написал для вас на node.js за 2 часа и которая перегружает сервер? Да! Вперед!

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

    Так что давайте, ржавейте. Тут весело.

    P.S. Хобби – разборка. Разбираю на части перегруженные серверные приложения. Сношу докер. Снижаю счета за AWS.

    Комментарии 313

      +16
      Восхитительный слог. Захватывающе, с сюжетом, по делу, без воды, на одном дыхании.
      Если Вам платят за рекламу раста, то мало. Если не платят, то должны начать:)

      Вопрос: на фрилансе rust вообще как, восстребован? Посматриваем куда уйти, смотрели на java/c#/c++, но сложилось ощущение, что эти языки только суровый офисный энтерпрайз.
        +2
        Спасибо. За рекламу мне ее платили. Я напишу в Раст что они должны :-)

        Во фрилансе я раста вообще не видел. Это все-таки суровый язык.
          –2

          В начале статьи был упомянут голанг — чем он не устроил? тот же standalone бинарник, скорость и отсутствие жопоразрывания borrow checker-ом — код пишется если не просто, то хотя бы без большого напряга. Если захотелось бы всякого нестандартного — можно было бы попробовать собрать проект через tinygo и получить похожий по размеру бинарник как и в расте.

            0

            Как говорится в очень старом и добром Скетч Шоу (https://m.vk.com/video-155258957_456239019):


            Но я не с вами флиртую!


            Хотелось попробовать и выучить раст. Посему я решил что голанг для этой цели не очень подойдет.

              +2

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

            +1

            Я, к сожалению, даже вакансий чисто на Rust не видел. Так что до фриланса он, может, лет через 10 доберётся. Если повезёт.

              +1

              Вакансии есть, но пока не особо густо. Из тех что предложены подходящих для себя я не нашел.

                +2
                Вполне себе появляются в ТГ чате — t.me/rust_jobs
                  0

                  Спасибо, душа радуется )

              +1

              Интересно написано. Я начинал серьёзно программировать ещё на asm i8080 (вернее КР580ВМ80А), нравилось байтики и даже битики считать. А потом покатился по С->С++->Perl->PHP с периодическими шарпами-джавами-нодами и т. п… На хлеб с маслом хватает, но часто скучать начал по тем временам. Вот чаще появляться стала мысль в качестве хобби какую-то экзотику изучить, чтоб было интересно. Начал Irdis, но не очень зашло — оторванно как-то от жизни. На rust имеет смысл писать что-то что обычно пишут на PHP/Java/C# веба с основной целью перехода — радоваться циферкам в htop? Или это на порядки больше времени?

                +7

                Зря вы так про идрис, это хаскель с завтипами done right. Его основная проблема не в оторванности от жизни, а в нулевой экосистеме. Возможно, через N лет станет лучше. Ну и ещё оно мозги прикольно выворачивает, начинаешь по-другому относиться к типам. По крайней мере, для меня идрис после хаскеля был примерно как хаскель после обычной императивщины.


                Возвращаясь к расту — забавно, как раз в эти выходные в порядке развлечения пролистал rust by example, кстати. По впечатлениям — хочется писать на нем то, что иначе писал бы на плюсах, где нужна максимальная близость к железу. Вебню с PHP/Java/C# писать на нем смысла не вижу, на хаскеле это делать приятнее и прикольнее.

                  +4

                  Веб на хаскеле? Так действительно делают?

                    +3

                    Делают. На прошлый проект к нам пришел дев, ушедший с проекта, где веб на Хаскале делали.

                      +6

                      Вот видите! Ушедший!

                      +1
                      Из того, что сразу в голову приходит github.com/hasura/graphql-engine
                      +4

                      Ну хаскель-код для меня как китайский текст почти ( А экосистема и есть приближенность к жизни.

                        +4

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

                          +2

                          Складывать из существующих кубиков (ругаясь сквозь зубы на монадические комбинаторы), наверно получится у всех. А вот в том, что все смогут полностью использовать возможности этого языка, я сильно сомневаюсь. У меня не получилось.

                            +3

                            Вопрос практики. Побороть лайфтаймы у меня заняло год неспешного разбора с языком (в продакшне это было бы 1-2 месяца думаю), у хаскелля все то же самое. Учиться пользоваться незнакомыми концепциями всегда сложно. На первом курсе универа у меня год заняло разобраться в том что такое циклы и массивы)

                              +1
                              На первом курсе универа у меня год заняло разобраться в том что такое циклы и массивы)


                              Поведу себя грубо и скажу, что это _преувеличение_ для красного словца.
                                0

                                Нет, совершенно не преувеличение. От необходимости обойти матрицу MxN и посчитать что-то (например среднее для каждого столбца) у меня наступала дикая паника и я не мог этого сделать. И только ближе к июньскому экзамену после сдачи РГР наконец до меня дошло, как с этим работать.

                                  0
                                  Это был эзотерический язык с неизвестным способом хранения данных в памяти? Или банальный Си? Если второе, то вот честно — какие были с этим сложности? Я в свое время преподавал ряд предметов программистского курса, и не припомню ни единого случая, чтобы кто-то не понял мое объяснение формата хранения двумерных массивов в Си.
                                    0

                                    Паскаль был обычный. Сложности — ну вот так у меня видимо мозг был устроен, я НЕ ПОНИМАЛ этого, никак. Первым ступором который занял у меня неделю наверное было i := i + 1. Если бы была сишная запись с обычным "равно" я бы наверное и две просидел. "как i может быть равно самому себе и ещё единице? Это бессмыслица". Понял, дальше пошло-поехало, с циклами особых бед не было, а потом появились массивы и я снова не мог с ними совладать. Но, в итоге понемногу вошел в ритм и дальше особых проблем не было аж вплоть до ООП.

                                      +1
                                      Не почему «равно», это же присваивание, в явном виде даже сделано в паскале так, чтобы было непохоже на «равно».

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

                                      В общем скорее непохоже на годный пример того, что «новые концепции всегда сложны». Просто есть простые концепции, а есть сложные (и иногда цена не оправданна).
                            +1

                            Хаскель я точно не пробовал.

                        +4

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


                        А еще можно веб серверы пилить. Actix-web прямо там и есть.


                        А еще можно заниматься абсолютно новомодным webassembly.


                        Ну и тут внезапно Microsoft увлеклась растом. Посему можно гуглить rust winrt.


                        Да и в ядре Линукса стало ржаветь потихоньку.

                          +2

                          Таки уже или все еще в процессе обсуждения?

                            +1

                            Смущает, что и время написания может сравниться с ассемблерным. А вот размер бинаря с некоторых пор перестал волновать: размер файлов данных программы и в ОЗУ важнее мне было. Сжатия на лету в памяти, битовые структуры и т. п.


                            Системное программирование как таковое, драйвера, ядра, инфраструктура мало уже интересует.

                              +4

                              Внезапно? То есть то что они 5 лет оплачивали Николаю Киму фуллтайм разработки актикса (и это только то что я достоверно знаю) это тогда что?)

                              0
                              На rust имеет смысл писать что-то что обычно пишут на PHP/Java/C# веба с основной целью перехода — радоваться циферкам в htop?
                              Если вы разрабатываете главную страницу Google – то да, стоит. В остальных случаях это не оправдано. Цена изменения кода на Rust сильно высокая, что идет в противоречие с «эджайл» стилем разработки типичного веба.
                                +1

                                Разрабатываю не главную страницу угла а просто сервис авторизации куда постоянно стучатся остальные сервисы. Выиграли по цпу, памяти, не потеряли в общем-то ничего. Не все гугл, но и не надо им быть

                                  +6
                                  Можете пояснить, что имеется в виду под «ценой изменения кода на Rust»?

                                  Разрабатываем самые обыкновенные веб сервисы, которые можно было бы делать и на Java, например.

                                  Команда довольна, инструментария и библиотек хватает, соседние отделы, насмотревшись на нас, тоже подтягиваются и начинают ржаветь, желания уходить обратно на Java нет.
                                    +7
                                    Цена изменения кода на Rust сильно высокая

                                    Цена чего конкретно? Изменять Rust-код довольно легко и безопасно, так как система типов у языка достаточно мощная и большинство ошибок отлавливает компилятор.

                                  +2
                                  За 3 недели раст выучить? Круто! Я уже с год разбираюсь, и то куча вопросов. Правда, в свободное время, когда руки доходят, но всё же.
                                    +3

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

                                      +3

                                      Ага особенно пробираться через trait objectы с async методами и хитрыми лайфтаймами. Ничего сложного

                                    +3
                                    Спасибо, очень актуальная для меня статья! Как раз эти выходные провел за изучением Раста. Ощущения очень сходные. То же возникли ощущения что читать книгу надо было в другом порядке.
                                      +2

                                      В книге предполагается, что показывается базовый синтаксис, а потом в дальнейших главах объясняется что вот эти типовые части можно прятать за сахар. Видимо авторы считают, что это более честный подход чем сначала показать сахар а потом когда человек столкнется с тем что не 100% сценариев покрывается "а вот тогда нужно руками расписать вот так". Я так понимаю, это подход, предлагаемый автором, и я о нем в целом писал пару лет назад.


                                      Но конечно это идет вразрез с маркетологовским "главное завлечь любыми средствами, а потом человеку будет неудобно менять инструмент и он останется". Есть же rust by example где как раз по идее более дружелюбно и "продажнически" преподносится как надо писать. А растбук это скорее справочник для тех кто знакомится с языком. Благодаря этому я весь растбук прочитал ну часов за 10 чистого времени. Сколько времени читается средняя книжка по го-питону с тонной воды и где не объясняется каким образом магическая магия работает думаю не надо говорить.

                                        +1

                                        Справедливости ради, в го магии не то, чтобы очень много :)
                                        Если не считать ей рантайм со сборщиком мусора и шелудером, конечно.

                                          +8

                                          Кстати был крайне удивлен, что в языке с ГЦ в 2020 году можно получить УБ на ровном месте, но вот можно.


                                          А магией можно считать даже стандартные типы, по крайней мере пока го 2.0 не выйдет.

                                            0

                                            А где вы в го наткнулись на UB?
                                            И в чем магия стандартных типов? Мне казалось, там всё максимально просто и явно сделано.

                                              0

                                              Вот код с УБ


                                              package main
                                              
                                              import "fmt"
                                              
                                              func surprise(a []int) {
                                                  a = append(a, 5)
                                                  for i := range(a) {
                                                      a[i] = 5
                                                  }
                                                  fmt.Println(a)
                                              }
                                              
                                              func main() {
                                                  a := []int{1} //  a := []int{1, 2}
                                                  a = append(a, 0)
                                                  surprise(a)
                                                  fmt.Println(a)
                                              }

                                              Про который вроде как знают, но вердикт ланг тимы "прост не пишите так": https://github.com/golang/go/issues/9458

                                                –1
                                                И про «прост не пишите так» вы мне только что сказали комментарием раньше :) Вот они, двойные стандарты
                                                habr.com/ru/post/537790/#comment_22574860
                                                  0

                                                  Между "Пишите" и "Не пишите" вы ведь разницу не видите, да?

                                                    0
                                                    Не вижу, да
                                                    Вы ответили «не копируйте», я на это обращал внимание. Для меня «не копируйте» == «не пишите»
                                                  –1
                                                  > Неопределённое поведение — свойство языков и библиотек в определённых ситуациях выдавать результат, зависящий от реализации компилятора (библиотеки, микросхемы) и случайных факторов

                                                  Здесь поведение вполне определено, есть одна явная реализация слайсов и функции append, которая работает вообще всегда одинаково и не зависит от случайных факторов. Зависит от неслучайных факторов, от аргументов (функция зависит от своих аргументов, звучит нормально). Поэтому давайте не делать вбросов насчёт UB в го :)
                                                  Но дизайн слайсов при этом действительно содержит опасные и неочевидные сразу места и я готов согласится, что можно было сделать его и как-то поочевиднее с точки зрения пользователя.

                                                    +4

                                                    Размер овераллокации при авторесайзе слайса не определён. Именно в этом месте возникает полноценное UB.

                                                      +3
                                                      Здесь поведение вполне определено, есть одна явная реализация слайсов и функции append, которая работает вообще всегда одинаково и не зависит от случайных факторов.

                                                      Серьезно? Вы Issue открывали?


                                                      On the playground, appending to an empty slice initializes the capacity to 2. This means that this will print "[0] [0 1]", because a and b share a buffer under those slice expansion rules. However, on my machine (64-bit Windows, go 1.4) an empty slice grows to a capacity of 1, and thus this prints "[0] [3 1]".

                                                      Если это по-вашему "всегда одинаково" то я даж не знаю.

                                                    –1
                                                    И в чем магия стандартных типов? Мне казалось, там всё максимально просто и явно сделано.

                                                    Слайсы, мапы и каналы можно параметризовывать типами. Встроенные дженерики, фактически. А вот свои делать нельзя. И делать для них итераторы тоже нельзя

                                                      –1
                                                      > Встроенные дженерики, фактически. А вот свои делать нельзя. И делать для них итераторы тоже нельзя
                                                      Это не является магией.
                                                      Даже не так, сами дженерики не являются магией, потому что принцип их работы очевиден, предсказуем и не требует понимания деталей реализации. Недоступность дженериков для использования пользователями и использование их в стандартной библиотеке тоже не является магией, потому что опять же, понятно, предсказуемо и не нужно ничего дополнительно знать для использования.

                                                      К слову, если вы считаете, что отсутствие дженериков это прям недостаток и что не добавили их просто потому, что создатели го — злодеи без чувства прекрасного, то почитайте к примеру про реализации дженериков в других языках и про трейдоффы, на которые приходится идти для этого.
                                                      Если кратко, то если делать дженерики в языке мономорфизмом, то есть генерировать на каждый набор параметров свою функцию, то вы сильно замедлите компиляцию (и ещё будут сложности с оптимизациями дженерик-кода) и раздуете бинарники.
                                                      А если делать дженерики, как в джаве, то есть делать одну дженерик-функцию, которая принимает абстрактные типы, то придётся принимать поинтеры, то есть, выделять память на хипе, то есть это ударит по перфомансу. И всё ещё будут проблемы с оптимизациями кода, потому что JITа в го как-то и нет :)
                                                      В сообществе го сейчас идёт большая дискуссия на тему того, как именно стоит сделать дженерики, чтобы получить больше бенефитов и поменьше всего испортить/замедлить.
                                                        +3

                                                        Но ведь для стандартных коллекций дженерики-то по сути есть! А вот пользователю этот инструмент не предоставляется. Если кого-то волнует раздувание кода и медленная компиляция, то он же может просто их не использовать.

                                                          +1
                                                          В сообществе го сейчас идёт большая дискуссия на тему того, как именно стоит сделать дженерики, чтобы получить больше бенефитов и поменьше всего испортить/замедлить.

                                                          Что не помешало накостылить те же мапы максимально мерзким способом.

                                                            +1
                                                            то почитайте к примеру про реализации дженериков в других языках и про трейдоффы, на которые приходится идти для этого.

                                                            С интересом почитаю про трейдоффы для дженериков в хаскеле. Только вот ничего не гуглится, не подскажете, что почитать?


                                                            Если кратко, то если делать дженерики в языке мономорфизмом, то есть генерировать на каждый набор параметров свою функцию, то вы сильно замедлите компиляцию (и ещё будут сложности с оптимизациями дженерик-кода) и раздуете бинарники.
                                                            А если делать дженерики, как в джаве, то есть делать одну дженерик-функцию, которая принимает абстрактные типы, то придётся принимать поинтеры, то есть, выделять память на хипе, то есть это ударит по перфомансу. И всё ещё будут проблемы с оптимизациями кода, потому что JITа в го как-то и нет :)

                                                            Если очень сильно упрощать, ghc для каждой «дженерик»-функции генерирует немономорфизированное тело, а в момент, когда конкретные значения типов становятся известны, подставляет конкретные параметры типов и выполняет все последующие оптимизации, от инлайнинга до мало ли чего.


                                                            При этом делается это только при компиляции с оптимизациями, где я могу себе позволить потратить время на оптимизатор. При компиляции без них (или при работе в репле) ничего этого не происходит, и компилятор отрабатывает очень быстро (но и код получается медленный, да).

                                                +20
                                                Добро пожаловать в нашу уютную ламповую секту!
                                                100-мегабайтное приложение на C# было заменено 564 килобайтами кода написанного на rust. 200 мегабайт памяти которые потребляло приложение на шарпах теперь превратились в 1.2 метра RAM для программы на rust. (Заодно избавился от двух докер-контейнеров в которых это приложение работало).
                                                Будь осторожен, это ощущение затягивает и вызывает зависимость! Еще неделю назад ты переписывал на Rust маленькое изолированное приложение, потом снижал счета на AWS, и вот уже организм требует переписать на него Linux kernel или Hadoop.

                                                Выходи почаще на улицу, общайся с друзьями. Помни – ты не можешь сделать весь мир эффективнее.
                                                  +1

                                                  Пишу раст приложение, которое запускаю в докере (причем не в альпине, в нем проблемисы, а в полноценном дебиане). Видимо я ненастоящий сварщик

                                                    +3
                                                    Помни – ты не можешь сделать весь мир эффективнее.

                                                    Но это не значит, что к этому не надо стремиться!


                                                    Tutum. Simul. Celerem.

                                                      –1
                                                      А чем плох С, на котором написано ядро линукса?)
                                                        +5

                                                        Тем, что писать на нём крупные проекты без внесения UB в код — задача, непосильная простым смертным.

                                                      +7
                                                      Я правильно понимаю, что задача считывать бинарные данные по сети с порта и сохранять с возможностью потом вытаскивания в виде CVS по датам?
                                                      Т.е. это одна таблица в БД фиксированного формата.
                                                      При том что 250Мб дамп памяти БД и +50Мб в год.

                                                      И для этой задачи: БД postgres (!!!!), C#, Node.js, docker и т.д.

                                                      ОФИГЕТЬ! Я всякое видел но такое…

                                                      С учетом накладных расходов Postgres на хранение данных, не нужна тут даже БД. Практически все данные в памяти поместятся.
                                                      Народ похоже уже даже не знает fseek функций для файлов…

                                                      Тут программка на C++/Java максимум строк на 500-1000 для такой задачи. Про rust не скажу. По работе не надо его. А ради любопытства — других вещей хватает.

                                                      Просто эталон как не надо решать задачи (я про то ПО, что было заменено).

                                                        +8

                                                        А потом ко всему этому делу матчер с непротиворечивыми регэкспами, парсинг и обработка времени децималы, персистентность, фаззи поиск и вот это вот все…
                                                        А можно взять уже написанное и слать запросы в базу.

                                                          +5
                                                          • regexp? Позиционно зависимые и фиксированные длинны. Приборы обычно другие и не выдают) из TCP/IP сокета.
                                                          • Обработка времени — это что? из строки получить Unix time (long int)?
                                                          • «фаззи поиск»… Поиск (дата) в памяти в упорядоченном массиве long int.

                                                          Для этих мелких задач нужно обязательно Postgres ставить?

                                                          А можно взять уже написанное и слать запросы в базу.

                                                          Вот тот лаборант так и поступил…
                                                          От результата я просто потащился.

                                                          Кстати, сплошь и рядом такое вижу, пусть и не в таких вырожденных формах.
                                                          Нужно сертификат x509 из PEM файла считать — добавляем Bouncy Castle
                                                          Нужно пару результатов select из таблицы вывести с простым маппингом имен полей в lowercase имена json (простейший микросервис) — а как же без hibernate то обойтись.

                                                          А уж как выглядит типичный package.json у JS…
                                                          «Зачем писать 2*2. Может где то уже есть библиотека на 200Мб где уже реализована функция mulTwoTwo»

                                                          Концепция «не надо изобретать велосипед» — это не догма.
                                                          Очень часто надо. Поскольку проще и быстрее. Когда понимаешь что делаешь, а не просто умеешь стыковать кубики.
                                                            +4
                                                            Позиционно зависимые и фиксированные длинны

                                                            как говорит старая народная мудрость — если у вас есть проблема и вы решаете ее regexp — у вас две проблемы. Даже в расте с его классными машинами состояний найдутся камни преткновения.


                                                            из строки получить Unix time (long int)?

                                                            а вот кто его знает в каком формате оно вообще у автора хранилось, хорошо если действительно unix timestamp, то проблема сведется к вызову ржавой API и конвертации строки в инт и обратно.


                                                            «фаззи поиск»… Поиск (дата) в памяти в упорядоченном массиве long int.

                                                            опять же — неизвестно какие данные у автора в базе — известно что там есть даты и есть какие-то валютные данные. fuzzy-поиск едва ли там действительно нужен, разве что веб-морде Ахо-Корасика навернуть для фильтрации по полям. Опять же автор упоминает, что большая часть запросов были про фильтрацию по дате, но это не все запросы. То бишь как минимум надо изобретать систему query, для работы с ними. Не очень тривиально и требует немало тестов по-хорошему. У раста с юнит-тестированием все конечно очень неплохо, но кому хочется писать тесты?
                                                            Короче велосипедить СУБД даже для данных с известным форматом — едва ли хорошая идея, стоящая затрат. Ну и автор вроде не настолько хлебушек, чтобы творить дичь из ваших примеров.

                                                          +5

                                                          Я правильно понимаю, что задача считывать бинарные данные по сети с порта и сохранять с возможностью потом вытаскивания в виде CVS по датам?
                                                          Т.е. это одна таблица в БД фиксированного формата.


                                                          И для этой задачи: fseek (!!!!), велосипедные индексы, самодельные проекции и т.д.


                                                          ОФИГЕТЬ! Я всякое видел но такое…


                                                          С учетом накладных расходов HTTP на передачу данных, не нужна тут даже память. Практически все данные можно стримить напрямую из БД.


                                                          Просто эталон как не надо решать задачи.

                                                            +2
                                                            Т.е. вместо простейшей консольный программы на C++/rust/Java в максимум 500 строк, которая в одном режиме (аргументы командной строки) стартует как demon или Windows service и:
                                                            0. Слушает сокет.
                                                            1. Получает данные из сокета (бинарные).
                                                            2. добавляет эти бинарные данные (C++ структура) с long int текущей даты конец файла.

                                                            А отдельный запуск этой же программы (с аргументами, например: "--from", "--to", "--outcvs") — получение csv файла, которая читает структурированные данные из файла и формирует csv.

                                                            Да я такие консольные утилиты и демоны(*nix)|сервисы (Win) довольно регулярно писал и пишу под подобные задачи.

                                                            Необходимо зачем то прикручивать HTTP и БД? Где Вы там все это увидели?
                                                            В описанном корявом решении лаборанта? внутри хостового служебного обмена между двумя программами? Потому что лаборант не знал как сразу из C# в БД сохранить?
                                                            Преобразовывала их в JSON, который был доступен через POST API. С шарпами он был не очень дружен, посему сохранять в базу данных всё решил на Node.js, который эту программу на шарпах дёргал, получал JSON, делал немного логики и гнал в базу данных (postgres)

                                                            Да еще Postgress! Если брать что то то по максимуму…

                                                            И да… 90% времени занимаюсь сервисами с http + json и хостовыми частями web и БД.

                                                            Но нафига все это для решения этой конкретной задачи «на входе читаем бинарные данные из сокета храни их и выдавай в файл по from->to критерию.
                                                              +1
                                                              подключается вот к этой системе, сгружает бинарные данные по сети с порта, конвертирует их в удобочитаемый формат и сохраняет всё в базу данных.

                                                              Уточнени… утилита не слушает сокет, а открывает и читает из него, перекладывая данные в файл. Те же яйца только вид в профиль.
                                                                +2
                                                                Т.е. вместо простейшей консольный программы на C++/rust/Java в максимум 500 строк, которая в одном режиме (аргументы командной строки) стартует как demon или Windows service и:
                                                                0. Слушает сокет.
                                                                1. Получает данные из сокета (бинарные).
                                                                2. добавляет эти бинарные данные (C++ структура) с long int текущей даты конец файла.

                                                                А отдельный запуск этой же программы (с аргументами, например: "--from", "--to", "--outcvs") — получение csv файла, которая читает структурированные данные из файла и формирует csv.


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

                                                                Необходимо зачем то прикручивать HTTP и БД? Где Вы там все это увидели?

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

                                                                Но нафига все это для решения этой конкретной задачи «на входе читаем бинарные данные из сокета храни их и выдавай в файл по from->to критерию.


                                                                Да потому что это преждевременная оптимизация сервиса, про требования к которому вы не знаете ничего. Если его вызывают раз в секунду то какая разница, хттп там или нет, есть БД или нет? Кроме того, база может быть файловая/инмемори, все эти sqlite/tarantool и прочее.

                                                                А требования: сегодня сортируем по from/to, а затра понадобилось выгрузку от конкретного юзера Х. И пошли пилить самодельные индексы. А потом понадобилось выгружать не все поля, а часть. Пошли писать SELECT'ы. И так далее.

                                                                По-дефолту нужно делать максимально просто, а не производительно, в условиях изначальных требований. Если там 1М RPS надо выдавать было изначально то ок, ваш подход возможно имеет смысл (хотя и там я бы взял существующие инмемори библиотеки), но я сильно сомневаюсь, что сервис который столько времени простоял в таком виде имеет такие требования.
                                                                  0
                                                                  А как без HTTP вы получите человеческую возможность взаимодействвоать с другими приложениями?

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

                                                                  К слову, может для кого то это и странно, но сплошь и рядом всякие отчеты/реестры забираются в банках не через HTTP вызовы, а передаются через SFTP или email.

                                                                  Решение на голом C++ для HTTP сервиса… Я не мазохист. Для этого другие инструменты.

                                                                  Да потому что это преждевременная оптимизация сервиса, про требования к которому вы не знаете ничего

                                                                  Преждевременная оптимизация — это БД, Web API и пр., когда не понятно нужно это будет или нет вообще.
                                                                  А консольная утилита с таким функционалом — пишется часа за 3-4 включая отладку.
                                                                  Поскольку делаю и то и другое, то могу оценить трудоемкость. И… самое противное объем технической документации на ПО. О чем все как то обычно забывают.
                                                                  На систему с БД+WEB API ее больше.

                                                                  А по ему опыту, всякие «наверное пригодится» выстреливают в 5-10% случаев. И то не совсем так, как предполагалось изначально.
                                                                    +1
                                                                    Я ее понял так как и сформулировал. Слов о внешнем интерфейсе получения выборок из данных в моей формулировки постановки не звучало.

                                                                    Всё бы хорошо, но поиска по полученным данным у нас не было.

                                                                    Кажется, звучало.


                                                                    Преждевременная оптимизация — это БД, Web API и пр., когда не понятно нужно это будет или нет вообще.

                                                                    Это не преждевременная оптимизация, потому что во-первых БД как правило уже есть, и вопрос только в том чтобы табличку там нужную создать, во-вторых потому что подключение какого-нибудь sqlite производится одной командой в пакетнике и гарантированно быстрее того чтобы писать это руками. Что тут говорить, я последние полгода занимаюсь переписыванием сервисов где решили сделать "свою простую базу". А что, казалось бы, задача элементарная: хранить сущности, возвращать их по некоторым простым условиям, иногда обновлять кусками или целиком. Но нет, триллионы багов: что-то не обновляется по каким-то причинам, при обновлении ключевого поля вроде id запись исчезает (и недоступна ни по старому айди, ни по новому), и прочие приколы.

                                                                +1
                                                                И для этой задачи: fseek (!!!!), велосипедные индексы, самодельные проекции и т.д.


                                                                тоже самое подумал при чтении )

                                                                если поиск по одному параметру то есть куча готовых key-value хранилищ, в том числе embedded типа (Mapdb, Sqlite, RocksDB и много других) которые отлажены и готовые. Если бы я пришел на уже написанное кем-то решение, я бы предпочел иметь дело со стандартными а не самописными инструментами.
                                                                +3
                                                                Прям вижу, как чувак набил портфолио и свалил в стартап )
                                                                  +1
                                                                  А похоже это ход такой. Был лаборантом, а стал со списком в резюме:
                                                                  JSON, C#, JS, Node.js, postgres, Doker, docker-compose

                                                                  Крутой список! Даже не мидл… такой список если правильно резюме оформить и на сеньера тянет…
                                                                  А если предыдущее место «секретнное», то и можно так в резюме подать, что и на лида.

                                                                  И возьмут же…
                                                                    +3

                                                                    Мне кажется, что сейчас такой список есть у каждого второго, да и в чем тут сеньорность? Поиграться с мейнстримными технологиями?
                                                                    Такой студент если и придёт на сеньора, то закономерно запнется на первом же вопросе сложнее helloworld.

                                                                      0
                                                                      Тэг <сарказм> я просто не добавил… Думал и так понятно.
                                                                      +3

                                                                      Уф, что-то, кажется, я зря в своём резюме только три с половиной технологии пишу, в которых более-менее уверен (Haskell, C++, Idris, Agda). Мог бы ещё с пару десятков ключевых слов добавить.

                                                                        +2

                                                                        Конечно зря, оно так и работает. К сожалению или счастью

                                                                  +1
                                                                  Очень содержательно, спасибо. Сам бодаюсь с ржавым 2-3 месяца, и соглашусь, борьба с областями видимости и владением далась нелегко. И документацию читал пару раз, если бы была эта статья раньше, возмжно, она бы ускорила мой прогресс)
                                                                    +1
                                                                    Были схожие ощущения от книги. Да и от самого языка
                                                                    Я обычно начинаю изучение новых языков с перелистывания документации и решения олимпиадных задачек. В расте же я со всей скорости врезался в непонимание ввода данных из консоли. Почему он такой сложный?
                                                                      +3
                                                                      Таков путь (с)
                                                                        +2

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


                                                                        let mut in = InputHelper::new();
                                                                        while in.read_line() {
                                                                          let n: usize = in.get();
                                                                          for _ in 0..n {
                                                                            let v: f32 = in.get();
                                                                            ...
                                                                          }
                                                                        }

                                                                        Здесь, все ошибки ввода приводят к аварийному завершению. Для более гибкой работы с консольным вводом есть крейты вроде read_input и text_io.

                                                                        +2
                                                                        Полный дамп базы данных весил 250Мб. Прирост данных составлял 50 метров в год.
                                                                        Еще и Постгресс надо было выкинуть при таких объемах.

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

                                                                        Про установку .NET и ее размеры — ну компилируйте под версию, встроенную в Win.
                                                                          +5
                                                                          Полный дамп базы данных весил 250Мб. Прирост данных составлял 50 метров в год. Чего там, тривиальная задача. Но всё это крутилось на выделенном сервере с 32 гигами оперативки и 24 процессорами. Сервер выл и жужжал потому что приходилось гнать 16 докер-контейнеров с кластером Elasticsearch, который постоянно рушился от перегрузки.

                                                                          Тут что-то не сходится. База в 250 мегабайт, прирост в 50 мегабайт в год — и сервак на 32 Гб и 24 процессоров? Кластер ELK? Ради выборок по датам и экспорта в CSV?
                                                                          Есть подозрение, что и будучи переписанным на шарпе профессиональным шарповиком оно бы жило значительно скромнее, нет? Не на расберри, конечно, но вполне рядовой виртуалке.
                                                                            +6

                                                                            Есть подозрение, что это было resume driven development (

                                                                            +4
                                                                            Недавно при написании одной из моих первых программ на Rust тоже нужно было как-то работать с Decimal и PostgreSQL. Решение тут как оказалось максимально простое и очевидное (но не для новичка, конечно):

                                                                            docs.rs/crate/rust_decimal/1.9.0/features

                                                                            У библиотеки rust_decimal есть features для того, чтобы интегрироваться в том числе с основными библиотеками баз данных

                                                                            Так что нужно было добавить что-то такое в Cargo.toml, и всё просто заработало:
                                                                            rust_decimal = {version = "*", features = [«db-tokio-postgres»]}
                                                                            tokio-postgres = "*"
                                                                              +1

                                                                              Никогда не используйте звездочку в зависимостях. Может больно шибануть.


                                                                              Мне как-то "звездочка" в зависимостях на гипер подсосала версию 0.0.1 при актуальной на тот момент 0.12.35

                                                                                +2
                                                                                Для программы в активной разработке (на старте) это может быть оправданно: проще посмотреть какая версия получилась заглянув в Cargo.lock, чем думать какую версию я хочу.

                                                                                Но так да, совет хороший. Оставлять такое надолго не стоит
                                                                                  +3

                                                                                  Обычно когда я делаю зависимость я беру последнюю которую иде подсказывает и не думаю:


                                                                                  img

                                                                                    +1

                                                                                    Ну или просто можно написать cargo add some_crate (https://github.com/killercup/cargo-edit) и тоже автоматически получить последнюю версию. Правда, в этом случае надо следить за тем, чтобы не получить альфу будущей мажорной ветки вместо стабильной версии.

                                                                                      +2

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


                                                                                      img

                                                                                        +2
                                                                                        Зачем? cargo-edit прекрасно поддерживает --features флаг
                                                                                          0

                                                                                          карго-эдит хорошая штука, но менее удобная, вот и все. Зачем мне второй инструмент если у меня в карго.томле всё прекрасно работает?

                                                                              +1
                                                                              А опишите свой опыт в создании REST API на расте. Например, как выглядит простейший CRUD, работа с JSON, с каким-нибудь S3, RabbitMQ, redis и проч.

                                                                              Вот недавняя статейка про это, TLDR человек намучался с простейшим API и пришел к выводу, что на вебе ему (пока) не место: macwright.com/2021/01/15/rust.html
                                                                                +2

                                                                                TLDR: берется актикс-веб, подключается к нему diesel/r2d2 (хотя если бы я делал с нуля я бы взял sqlx вместо этого), реббит-редис работается так же как и любой другой язык.


                                                                                Из минусов — отсутствие диая (то есть хендлеры знают, что нужно таскать из хедеров, что из тела, что из кверистринги, такой вот сервислокатор) и отсутствие генерилки опенапи описания по хендлерам: мы руками правим swagger.json и отдаем как статику вместе со swaggerUI.


                                                                                Что до статьи которая линкуется — хз, мне не показалось что сделать простейшее апи сложнее чем с какимнеибудь экспресс-жс:


                                                                                img


                                                                                Чуть больше конкретики


                                                                                Rust has a fair number of web server frameworks, database connectors, and parsers. But building authentication? You have only very low-level parts. Where Node.js will give you passport and Rails has devise and Django gives you an auth model out of the box, in Rust you’re going to build this system by learning how to shuttle a shared vec into low-level crypto libraries. There are libraries trying to fix this, like libreauth, but they’re nascent and niche. Repeat for plenty of other web framework problem areas.

                                                                                Видимо под "you’re going to build this system by learning how to shuttle a shared vec into low-level crypto libraries" имеется в виду вот этот код:


                                                                                pub fn validate_and_enrich(
                                                                                    &self,
                                                                                    req: ServiceRequest,
                                                                                    credentials: &BearerAuth,
                                                                                ) -> impl Future<Output = Result<ServiceRequest, actix_web::Error>> {
                                                                                    let f = self.auth_client.get_user_info(credentials);
                                                                                    async move {
                                                                                        let user_model = f.await?;
                                                                                        req.extensions_mut().insert(user_model);
                                                                                        Ok(req)
                                                                                    }
                                                                                }
                                                                                
                                                                                ...
                                                                                
                                                                                let auth = HttpAuthentication::bearer(move |req, c| auth.validate_and_enrich(req, &c));
                                                                                self.service(resource(path).route(route).wrap(auth))

                                                                                Ну да, я практически стал специалистом по криптографии когда это написал )


                                                                                Ну и далее по тексту


                                                                                Rust makes you think about dimensions of your code that matter tremendously for systems programming. It makes you think about how memory is shared or copied. It makes you think about real but unlikely corner cases and make sure that they’re handled. It helps you write code that’s incredibly efficient in every possible way.

                                                                                These are all valid concerns. But for most web applications, they’re not the most important concerns. And buzzword-oriented thinking around them leads to some incorrect assumptions.

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

                                                                                  +1
                                                                                  я бы взял sqlx вместо этого


                                                                                  PsyHaSTe подскажите, а у вас работает intelli sense в IDE/text editor с sqlx макросами (да и вообще с макросами)? Я пробовал пару раз sqlx (у самого IDEA c Rust плагином), но как только дописываю ключевое слово макроса на этом помощь IDE заканчивается.
                                                                                    +1

                                                                                    С макросами работает, но через раз. Я обычно Владу Бескровному баги завожу, он их понемногу поправляет, последний раз жаловался на макросы дизеля. Но у sqlx скорее всего процедурные, а там вряд ли IDE может помочь.


                                                                                    Что до sqlx макросов то я в целом негативно отношусь к макросам, которые лазят куда-то во внешний мир, а sqlx насколько я понял из доки лезет в БД чтобы проверить схему. Таким образом, если у меня нет актуальной схемы БД (по любой из миллиону причин) то собрать код я не могу. Поэтому, простой кверибилдер думаю будет предпочтительнее.


                                                                                    Идеальным мне кажется подход EF с code first когда схема БД хранится в коде и в БД может накатываться при желании. Тогда сборке не надо смотреть куда-то, она самодостаточная, но при этом и гарантии типчиков мы сохраняем. Но увы, не все коту масленница.

                                                                                +4
                                                                                Офигенная статья! Единственное что мой граммар-наци забодался ctrl-enter жать. ;-)
                                                                                  –2
                                                                                  И хотя rust и не такой сложный как Си в управлении памятью и ссылками

                                                                                  Хм… всё как раз наоборот.

                                                                                    +8

                                                                                    раст как раз появился потому, что управлять правильно ссылками в си — сложно. А если неправильно то неважно насколько это легко

                                                                                      0
                                                                                      Мммм, а вы могли бы пояснить? Потому что, да, управлять памятью в Си — в бесконечное число раз проще чем вообще где-либо еще. Да, конечно _тяжелее_, чем в плюсах например, но при этом _проще_.

                                                                                      А за этим вот «правильно — неправильно» обычно прячется маркетинг, нет?
                                                                                        +4

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


                                                                                        Так что пример с простым управлением напоминает Марка Твена, которому очень просто бросить курить.

                                                                                          –1
                                                                                          Это старая песня — зайдите и посмотрите, ага. И я даже не буду просить у вас конкретных примеров, ибо знаю их — тут забыли, тут не в том порядке освободили, и так далее. Но это все не про «секреты правильного управления», это как раз подтверждает мои слова — управлять памятью в Си просто, но тяжело, требует внимания. В плюсах произошел рост сложности управления с одновременным облегчением этого самого управления в бизнес-логике — и наверное вы не будете спорить, что в плюсах стрелять в ногу стало несравненно интереснее. Проводя современные аналогии — в Си вы работаете в тубдиспансере, все время ходите в маске и моете руки раствором хлорки, и если забыли что-то из этого — то заболеете. И вас можно проверить на количество использованной хлорки, чтобы поймать вашу ошибку — хотя для этого опять же нужен отдельный линтер человек. В плюсах у вас нет с собой раствора хлорки, потому что Александр Степанов приделал к каждой двери автоматический распрыскиватель, но если вдруг вы нажали ручку двери не с тем ускорением — распрыскиватель как будто бы работает, но на самом деле нет, и вы об этом никогда не узнаете, либо увидите такое сообщение, что просто не поймете его достаточно хорошо и попробуете выйти в другую дверь (а там лежат туберкулезники с Эболой, но об этом вы узнаете потом может быть).

                                                                                          Продолжая аналогию — в Расте вы скорее всего вообще не сможете зайти в тубдиспансер. Хотя если вы очень опытный доктор и пять месяцев были на курсах повышения квалификации… То сможете иногда заходить )))
                                                                                            +5
                                                                                            Но это все не про «секреты правильного управления», это как раз подтверждает мои слова — управлять памятью в Си просто, но тяжело, требует внимания.

                                                                                            Остается тогда заключать что самый простой (и, видимо, лучший?) язык это брейнфак, куда проще сишки: всего 6 операторов и никаких странных правил и УБ.


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

                                                                                              +1
                                                                                              Поскольку на нем очевидно нельзя написать за разумное время вообще никакую сложную программу — не соглашусь.

                                                                                              Хотя это уже спор из серии «а что такое достаточно сложная программа».
                                                                                              +2

                                                                                              Можно и другую аналогию привести. В Boeing 737 MAX конструкторы положились на квалификацию экипажа, на то, что экипаж распознает нештатную ситуацию с датчиком угла атаки и примет нужные меры (как язык С полагается на квалификацию программистов). В Airbus сделали мажоритарное троирование датчиков, чтобы не полагаться на экипаж, но экипаж может отключить эту систему (как в managed языках и расте).


                                                                                              Результаты известны.

                                                                                                0
                                                                                                Ммм, нет, в Эрбасе просто есть статанализатор — и он обязателен.

                                                                                                И вообще пример с MCAS он как раз скорее про обратное, про сахар и «все под капотом сделано умными людьми» — есть все нужные подписки, память освобождается где нужно, думать не требуется. Ну вот и не подумали потом в продакшене…
                                                                                                  +6

                                                                                                  В эрбасе под капотом сделали сложно, но надёжно. И если что не так, то по индикации всё видно.


                                                                                                  MCAS — под капотом всё просто (предельный угол атаки на одном датчике? корректируем), прямой индикации наличия проблемы нет, экипаж должен быть начеку и всё понять по косвенным признакам.

                                                                                                    0
                                                                                                    Ненене, MCAS как раз про «вся сложность под капотом», плюс закон протекающих абстракций Спольск. «Все просто под капотом» — это Ту-154.

                                                                                                    Короче аналогии нас куда-то завели…
                                                                                                      +5

                                                                                                      Ту-154? Третий по аварийности в мировом рейтинге? Вроде всё правильно: не стоит рассчитывать что люди всё будут делать безошибочно, если их не подстраховывать автоматикой. Ну и не стоит рассчитывать, что люди будут использовать автоматику, если она доставляет им малейшие неудобства, если её им не навязать.

                                                                                                        0
                                                                                                        При чем тут аварийность? 0_о

                                                                                                        Мда, короче и тут аналогии увели нас совсем в другую сторону. Зря я это начал…
                                                                                                          +3
                                                                                                          Так именно в эту же: если инструмент «тонкий», то пользоваться им сложно (или тяжело, что с точки зрения пользователя почти одно и то же).
                                                                                                          Нужны абстракции правильной толщины — если абстракция слишком бедная, то ей пользоваться сложно (не с точки зрения предсказания, какой получится результат выполнения этой одной строчки, а с точки зрения того, как эта одна строчка влияет на всю программу), потому что она позволяет слишком большим количеством способов отстрелить себе ногу.
                                                                                                          А если слишком богатая, то оказывается сложно предсказать поведение системы «под капотом» (например, в случае управления памятью это будет сборщик мусора, который добавляет новые задержки, над которыми нет контроля).
                                                                                                            0
                                                                                                            Да, и поэтому связка С+C# в принципе решает все задачи, стоящие перед человечеством.
                                                                                                              +1
                                                                                                              Зачем C и C#?

                                                                                                              Чистый ассемблер уже является тьюринг-полным.
                                                                                                                0
                                                                                                                GC нет, так что богатая абстракция не покрыта.
                                                                                                                  +3

                                                                                                                  C# не функциональный язык, так что там много других богатых абстракций не покрыто.

                                                                                                                    –1
                                                                                                                    Ну, да, я говорил скорее про императивные языки.
                                                                                                                +3
                                                                                                                Да, и поэтому связка С+C# в принципе решает все задачи, стоящие перед человечеством.

                                                                                                                И как же эта связка решает задачу обработки ошибок?

                                                                                                                  0
                                                                                                                  В одном случае — руками, в другом — под капотом красивый сборщик мусора. Если мы про проблемы с управлением памятью.
                                                                                                                    +3
                                                                                                                    Если мы про проблемы с управлением памятью.

                                                                                                                    Нет, я про ошибки в принципе. Навроде "Файл не удалось прочитать" или "Число не удалось распарсить"

                                                                                                                      0
                                                                                                                      Эм… Ну, так же, как и в других языках… или я не так вас понял?
                                                                                                                        +4

                                                                                                                        Монады в C# выглядят как-то не очень.

                                                                                                                          +1

                                                                                                                          В каких других? На ошибки в расте похоже? В хаскелле? В каком-нибудь erlang?

                                                                                                                            –1
                                                                                                                            В любых. Отсутствие файла — проблема для любого языка, логично?
                                                                                                                              0

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

                                                                                                                                –1
                                                                                                                                Семантика действий будет как-то отличаться? Или просто «исключения фу, нужны коды ошибок»? В чем суть диалога этого?
                                                                                                                                  +1

                                                                                                                                  В том, что раст дает безопасность "функция всегда вернет результат и ошибки не будет" на уровне сигнатуры, а джава — нет. В джаве вы функцию int Foo(int x) => x*x можете переделать в


                                                                                                                                  int Foo(int x) { 
                                                                                                                                    if (x == 0) throw new SomethingException();
                                                                                                                                    return x*x:
                                                                                                                                  }

                                                                                                                                  А в расте подобное изменение — ломающее и приведет к ошибке компиляции (т.е. невидимый эксепшн в продакшн не пролезет таким образом). Ну и так далее.

                                                                                                                                    –2
                                                                                                                                    Ииии… И что?

                                                                                                                                    Я специально выше написал — ну ок, будут у вас вместо исключений коды ошибок. Какая разница? Если для вас важно, что Х не может быть нулевым, то вы либо бросаете исключение, либо возвращаете nullable-тип, возьмем эти два варианта. еще раз — если для вас это важно, то вы сообщаете это из функции и обрабатываете это. Если неважно — не обрабатываете.

                                                                                                                                    Почему мы это обсуждаем?
                                                                                                                                      +2

                                                                                                                                      Такая что добавление необрабатываемого кода ошибка приводит к ошибке компиляции. А добавление нового вида эксепшнов — к "упс" на проде

                                                                                                                                        –3
                                                                                                                                        То есть вы акцентируете внимание на том, что в одном случае вы _обязаны_ обработать все коды ошибок на уровне правил написания, а в другом случае вы эти правила можете обойти? Ну так это вопрос code of conduct и статанализаторов. Ну и вас же, очевидно, не надо учить тому, как обработать все коды ошибок, но сделать это так, чтобы было бесконечно больно? :)
                                                                                                                                          +1

                                                                                                                                          У вас нет никакого способа сказать что функция Foo бросает вот эти исключения. Точнее есть — чекед эксепшны, тока ими никто не пользуется. И нет, не потому что сама идея проверки возможных ошибок в компайл тайм порочна, а потому что сами чекед эксепшны слабы. Обсуждалось уже не раз.

                                                                                                                                            0
                                                                                                                                            Я повторю свой вопрос, возможно после этого обсуждать будет нечего — мы вот реально от обсуждения управления памятью пришли сюда, к обсуждению исключений, чтобы написать, что исключения хуже, чем коды ошибок функций?
                                                                                                                                            +2
                                                                                                                                            Ну так это вопрос code of conduct и статанализаторов.

                                                                                                                                            Ну то есть опять честное слово и прикручнные сбоку на изоленту костыли.

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

                                                                                                                                              В случае с честным словом, статанализатором (который повторяющиеся куски кода покажет) и очевидным в данном случае код-ревью хотя бы кто-то вас поймает за этим делом…
                                                                                                                                                +1

                                                                                                                                                Главное — что вы его напишете и не забудете. А явную лажу (вроде unwrap без обработки) будет ещё лучше видно на кодревью (которые не стоит выкидывать в любом языке).

                                                                                                                                                  0
                                                                                                                                                  Ровно, ровно наоборот! Написав какую-то лажу вы как раз таки спрячете проблему, она не проявится даже в рантайме. К сожалению очень много таких проблем я видел…

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

                                                                                                                                                  Я еще вот что поясню — мне ваша общая претензия к исключениям понятна, в этом смысле я на одной стороне баррикад с тем известным китайцем из МС. Но скорее поднимать это на щит я не готов. А тем более вспоминать про это при обсуждении механизмов управления памятью…
                                                                                                                                                    +1

                                                                                                                                                    Так система типов — это как раз ваш статанализатор.


                                                                                                                                                    Да и кто мешает заткнуть этот самый статанализатор точно так же, как вы предлагаете заткнуть тайпчекер?

                                                                                                                                                      0
                                                                                                                                                      Ну если в правилах есть, что не должно быть повторяющегося кода, то СА решит вопрос, а система типов?
                                                                                                                                                        0

                                                                                                                                                        Мы же вроде обсуждали написание лажи и игнорирование ошибок.

                                                                                                                                                          0
                                                                                                                                                          Что будет видно анализатором, да.
                                                                                                                                                            +3

                                                                                                                                                            А чтобы увидеть ошибки, которые проигнорированы (намеренно, например) анализатором, мы сделаем анализатор анализатора!

                                                                                                                                                              –2
                                                                                                                                                              Это как? Я не понял. У нас плохой анализатор?
                                                                                                                                                                +2

                                                                                                                                                                Даже если идеальный (чего не бывает), то, может, там написано


                                                                                                                                                                namespace ConversionUtils
                                                                                                                                                                {
                                                                                                                                                                  std::optional toInt(const std::string&);
                                                                                                                                                                }
                                                                                                                                                                
                                                                                                                                                                int readInt(std::string path)
                                                                                                                                                                {
                                                                                                                                                                  /// mySuperDuperAnalyzer:ignoreExceptions
                                                                                                                                                                  File file { std::move(path) };
                                                                                                                                                                  /// mySuperDuperAnalyzer:ignoreExceptions
                                                                                                                                                                  auto str = file.readAll();
                                                                                                                                                                  if (str.empty())
                                                                                                                                                                  {
                                                                                                                                                                    // mySuperDuperAnalyzer:ignoreUsingMovedFromObject
                                                                                                                                                                    Logger() << "can't read " << path;
                                                                                                                                                                    return -1;
                                                                                                                                                                  }
                                                                                                                                                                  /// mySuperDuperAnalyzer:ignoreUncheckedOptionalValue
                                                                                                                                                                  return ConversionUtils::toInt(str).value();
                                                                                                                                                                }
                                                                                                                                                                  +2

                                                                                                                                                                  Так обязательно должен быть комментарий // abusing knowledge that X does Y when Z, и чуть ниже коммит который вставляет доп проверку с тегом #[fixed(since = "2021-05-05", reason = "add additional checks for situation when Y doesn't do Z")]

                                                                                                                                                                    –1
                                                                                                                                                                    Ну это уж чересчур )))
                                                                                                            +6

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

                                                                                                              0
                                                                                                              В принципе вы правы, хотя я бы не был все же так категоричен. Потому что «сразу сделать все правильно» — не выглядит реализуемой технической концепцией, а вот постепенно допиливать какую-то систему обеспечения правильности — обыденно.
                                                                                                                +5

                                                                                                                Только если с точки зрения её восприятия человеком, а это вопрос скорее социальный, чем технический. Корректные и выразительные системы обеспечения правильности известны лет 40-50, языки с ними существуют лет 30, так что технически концепция как раз вполне реализуема.

                                                                                                                  0
                                                                                                                  Вы все верно пишете, но вспоминается ленинский принцип «пусть социал-демократы продемонстрируют, как именно они планируют это делать, а не говорить».
                                                                                                                    +1

                                                                                                                    CompCert, seL4.


                                                                                                                    И, кстати, в статье от авторов CSmith про CompCert отдельно сказано:


                                                                                                                    The striking thing about our CompCert results is that the middle-end bugs we found in all other compilers are absent. As of early 2011, the under-development version of CompCert is the only compiler we have tested for which Csmith cannot find wrong-code errors. This is not for lack of trying: we have devoted about six CPU-years to the task. The apparent unbreakability of CompCert supports a strong argument that developing compiler optimizations within a proof framework, where safety checks are explicit and machine-checked, has tangible benefits for compiler users.

                                                                                                                      –1
                                                                                                                      Извините, я не понял, к чему вы привели эти ссылки. Они как раз подтверждают _мои_ слова.
                                                                                                                        +1
                                                                                                                        Надо-же! Кто-то про seL4 микроядрышко вспомнил…
                                                                                                                        +4

                                                                                                                        Ну вот одна из компаний, с которой я потихоньку в ленивом режиме веду переговоры о работе, как раз занимается формальной верификацией языка для умных контрактов для некоего блокчейна. Правда, на коке, к сожалению. Не люблю кок.

                                                                                                                          –1
                                                                                                                          Вот, да, контракты для блокчейна. И все равно это редкая редкость. И все равно непонятно, при чем тут Раст.
                                                                                                                            +2

                                                                                                                            Он — ещё одна точка. Даёт меньше гарантий, чем та наркомания, но писать проще.

                                                                                                          +3
                                                                                                          Вопрос в том, как измерять сложность.
                                                                                                          Каждая отдельная команда управление памятью — проще, конечно, в С.
                                                                                                          Но для не-тривиальной программы на С, следить (руками) за всеми инвариантами (чтобы не получить use after free, double free, etc) уже сложнее (хотя каждый отдельный примитив по-прежнему проще).
                                                                                                            0
                                                                                                            Я вас поправлю, извините — _тяжелее_, а не _сложнее_.

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

                                                                                                            А вообще я зря начала эту ветку обсуждения, прошу прощения, можно ее закрывать. Она к этой статье не к месту.
                                                                                                              +2
                                                                                                              Как раз эта ветка очень к месту. Ибо не всем понятно что за то, чтобы иметь одновременно безопасность и управление памятью надо чем-то платить. Вот некоторые и не хотят платить…
                                                                                                                +3
                                                                                                                Ибо не всем понятно что за то, чтобы иметь одновременно безопасность и управление памятью надо чем-то платить.

                                                                                                                А чем, собственно говоря, платить?

                                                                                                                  +1
                                                                                                                  Сложностью изучения необходимой технологии же.
                                                                                                                    0
                                                                                                                    Тут стало неясно. Ваши исходные пойнты — безопасность и управление памятью. Это все делается и в Джаве например, и там как раз нет большой сложности в изучении.

                                                                                                                    Раст за счет совершенно другой концепции обеспечивает еще и скорость, но сложность возрастает критически…
                                                                                                                      +3
                                                                                                                      Так бейзлайн не Джава, а С.

                                                                                                                      Тезис примерно такой: Написать большое приложение на С так, чтобы там не было проблем с памятью сложнее, чем написать приложение на Расте, чтобы там не было проблем с памятью.
                                                                                                                      Несмотря на то, что написать однострочник на С, конечно, проще.
                                                                                                                        0
                                                                                                                        Вот именно этот тезис кажется надуманным. Просто для сравнения нужны примеры, и у Си они есть, а у Раста мало что вообще есть. Где-то там есть, у социал-демократов, но не тут. И причина же ясна — сложность высокая у языка.
                                                                                                                          +4
                                                                                                                          Просто для сравнения нужны примеры, и у Си они есть, а у Раста мало что вообще есть.

                                                                                                                          Хмммм.


                                                                                                                          Хммммммммм.


                                                                                                                          Хммммммммммммммммм.

                                                                                                                            –1
                                                                                                                            Опять ссылки, непонятно что доказывающие. Вот мы знаем например, на чем написана ОС Integrity, примем это за некий уважаемый пример. И она в принципе довольно сложна, да. И как-то получилось, угу. Теперь давайте посмотрим на симметричный ответ на Расте и попытаемся понять, насколько использование Раста в этом примере сэкономило авторам какие-то ресурсы, или, возьмем выше, сделало реализацию проекта вообще возможной.
                                                                                                                              +2
                                                                                                                              Проблема такая:
                                                                                                                              И она в принципе довольно сложна, да. И как-то получилось, угу.

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

                                                                                                                              В то, что на С написать программу, которая иногда работает проще, чем на расте написать программу, которая иногда работает — никто не спорит.
                                                                                                                                –2
                                                                                                                                Ну, да, поскольку симметричного ответа нет — нечего и обсуждать, я вас понял))
                                                                                                                                  +4

                                                                                                                                  Симмеетричный — это написаная ОС? Пожалуйста, есть redox.


                                                                                                                                  Что до утверждений "да вы посмотрите на си вон линукс есть и Integrity" — если на протяжении 40 лет вливать миллионы (миллиарды?) долларов и тысячи человеколет в проект то можно и на брейнфаке его завести. Качество языка это показывает никк, кроме того, что когда их писали 40 лет назад из альтернатив был паскаль и лисп. Только эти годы индустрия не спала и что-то придумывала. Аргумент "деды писали и нам велели" такой себе

                                                                                                                                    –1
                                                                                                                                    Не, осей уровня Редокс — и на Си тележка. Предполагался симметричный пример.

                                                                                                                                    Из вашего второго абзаца очевидно следует, что на Расте такие же операционные системы будут написаны за 4 года усилиями пяти человек? Что же, думаю скоро мы это увидим.
                                                                                                                                      0

                                                                                                                                      За 40 лет, да. Давайте, 21.01.2061 откопаю тред и напишу что вышло.

                                                                                                                                        0
                                                                                                                                        Эмммм, а зачем нам тогда Раст, если надо снова сорок лет? Вы же говорили, что на нем…

                                                                                                                                        А впрочем неважно, пора завязывать это бессмысленное обсуждение.
                                                                                                                                      0
                                                                                                                                      На яве тоже когда-то писали OS
                                                                                                                          +3
                                                                                                                          Ваши исходные пойнты — безопасность и управление памятью. Это все делается и в Джаве например

                                                                                                                          В Java есть ConcurrentModificationException, которое в Rust просто не требуется.

                                                                                                                            –2
                                                                                                                            Я не понял, наличие данного эксепшна — это проблема? И как это связано с управлением памятью например?
                                                                                                                              +8

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

                                                                                                                                –2
                                                                                                                                Извините, это «за все хорошее против всего плохого». Очевидно, что лучше в компилтайме.

                                                                                                                                Я просто не пойму, куда клонит комментатор выше. Разговор выгляди так:
                                                                                                                                1) Ручное управление памятью — фу.
                                                                                                                                2) Берите джаву, там не ручное.
                                                                                                                                3) В джаве эксепшоны.
                                                                                                                                4) Ииии… чо?

                                                                                                                                Эксепшоны — механизм _для всего_, не только для решения проблем с памятью, но и с ошибками арифметики, выходом за границы (есть много где, и везде не бесплатно), таймаутами и черт знает чем. Когда у вас в рантайме из-за SET флаг carry установится, а потом ответный пакет не придет, вы на компилтайм как молиться будете — сидя или стоя? или может нам понадобятся эксепшоны/прерывания/коды_ошибок?
                                                                                                                                  +3
                                                                                                                                  Ииии… чо?

                                                                                                                                  А в расте они не нужны для этого. Раст даёт больше статических гарантий.


                                                                                                                                  Эксепшоны — механизм для всего

                                                                                                                                  Но это не значит, что их надо использовать для всего (или вообще что надо использовать).


                                                                                                                                  выходом за границы (есть много где, и везде не бесплатно)

                                                                                                                                  В упомянутых рядом языках можно сделать бесплатно настолько, насколько это возможно (то есть, валидировать только пользовательский ввод, скажем, и математически минимально необходимое число раз — скажем, если вы в рантайме проверили, что i < len(arr), и вы знаете, что arr имеет больше одного элемента, то в рантайме проверять, что i / 2 + 1 < len(arr) уже не нужно).


                                                                                                                                  Когда у вас в рантайме из-за SET флаг carry установится, а потом ответный пакет не придет, вы на компилтайм как молиться будете — сидя или стоя?

                                                                                                                                  Я не понял, как связаны флаги и ответный пакет.

                                                                                                                                    –1
                                                                                                                                    Но это не значит, что их надо использовать для всего (или вообще что надо использовать).


                                                                                                                                    Еще раз — положим, что возможна какая-то ошибка. Они бывают разные. Так или иначе их надо обрабатывать. Исключения — один из механизмов. С его помощью можно построить логичную систему обработки любых ошибок, в том числе ошибки, упомянутой выше. ЗАЧЕМ вообще мы все это здесь обсуждаем? Зачем это было упомянуто при обсуждении управления памятью? Где логика? Просто чтобы лишний раз пнуть условную Джаву и сказать, что Раст хороший?

                                                                                                                                    Я не понял, как связаны флаги и ответный пакет.


                                                                                                                                    Никак. Это примеры двух разных ошибок в рантайме, которые надо как-то обрабатывать. Раз уж мы зачем-то (повторяю — не по моей инициативе) начали обсуждать исключения и то, что статические гарантии конечно гораздо лучше.
                                                                                                                                      +2
                                                                                                                                      Еще раз — положим, что возможна какая-то ошибка. Они бывают разные. Так или иначе их надо обрабатывать. Исключения — один из механизмов. С его помощью можно построить логичную систему обработки любых ошибок, в том числе ошибки, упомянутой выше. ЗАЧЕМ вообще мы все это здесь обсуждаем? Зачем это было упомянуто при обсуждении управления памятью? Где логика? Просто чтобы лишний раз пнуть условную Джаву и сказать, что Раст хороший?

                                                                                                                                      С тем, что джава по-умолчанию делает "Необрабатываемые исключения" которые нужно явно обработать трай кетчем, а раст — не разрешает так делать и требует обработать все кейсы явно. Потому что в расте ошибки можно нормально комбинировать. Ошибка из библиотеки А и библиотеки Б при попытке их скомбинировать становится ошибкой A | B. В джаве всё один Exception.


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

                                                                                                                                        0
                                                                                                                                        Вы когда-нибудь обрабатывали ошибки как-то по особому, кроме как «вывести в лог и жить дальше»?
                                                                                                                                          +1
                                                                                                                                          let application_url = config
                                                                                                                                                  .application_url
                                                                                                                                                  .as_ref()
                                                                                                                                                  .map(|x| x.as_str())
                                                                                                                                                  .unwrap_or("0.0.0.0:8800")

                                                                                                                                          Попытались считать из конфига урл для запуска, если не вышло, запускаемся на локалхосте на 8800 порту

                                                                                                                                            0