Мы побеседовали с руководителем направления системного программирования в «Криптоните» Александром Авраменко о карьерном пути Rust-разработчика, особенностях языка Rust и его применении к моделям машинного обучения в высоконагруженных системах. — Александр, расскажи о своём карьерном пути.  — Я учился в МАИ, получил диплом с отличием по специальности «бортовые системы». Всегда любил вычислительную технику и программирование. Уже в те времена был язык С, на котором я помогал писать пользовательские интерфейсы, заготовки для лабораторного САПРа и т.д. Затем работал в ОКБ Сухого, делал ПО лётного тренажёра. В «живой» кабине с вмонтированными экранами подключался наш софт. Мы визуализировали облака, землю, аэродромы, рисовали карты, план полёта, индикаторы...  Потом я перешёл работать в блокчейн как в очень перспективную и технологически интересную область. Этот проект тоже был доведён до продакшена — мы запустили главную сеть. Как раз тогда, примерно в 2019 году, я обратил внимание, что некоторые новые блокчейны пишутся на языке Rust. Я им заинтересовался, изучил книгу и понял, насколько это интереснее, чем С++. После этого в 2020 году поступило предложение от «Криптонита». Я принял его, так как мне как раз хотелось погрузиться в новый масштабный проект. — Чем ты занимаешься в «Криптоните»?  — Я возглавляю группу системного программирования на Rust. Мы создаём сетевые сервисы и конвейеры обработки потоков больших данных с применением моделей машинного обучения (ML) в реальном времени.  Ранее Александр поделился с нами лайфхаками по управлению группой разработчиков: он рассказал о «подводных камнях» на собеседовании, мотивации команды и ситуации на рынке труда «растистов». Это могут быть разные данные: картинки, видео- и аудиозаписи… любые файлы, которые наш пользователь хочет как-то обрабатывать. Обычно такие большие объёмы данных обрабатываются моделями машинного обучения. И здесь возникает технически сложная задача: написать такой софт, который, с одной стороны, обеспечит непрерывный поток входных данных, а с другой — подаст их на вход моделям. А ещё он будет накапливать результаты, которые эти модели формируют, складывать их в хранилище, систематизировать и делать это в режиме 24/7 в течение месяцев без перезагрузки. — То есть должна быть сбалансированная система с буферизацией, классификацией, сортировкой данных… — Да, и не в последнюю очередь — высокопроизводительная, потому что все эти этапы требуют больших вычислительных ресурсов. Если мы не будем использовать ресурсы эффективно, то сильно увеличим затраты на аппаратное обеспечение. — Насколько представляю, основная задача здесь — быстрее освобождать память? Высоконагруженные системы страдают любовью «отжирать» её. — Всё верно. Ещё, когда приступаешь к такой задаче, слегка обескураживает обилие процессорных ядер и вычислительных потоков, которые нужно балансировать динамически. Поток данных то увеличивается, то уменьшается, когда-то необходимо отправлять результаты на сохранение, поскольку они постоянно накапливаются. В зависимости от текущих потребностей необходимо перераспределять общие вычислительные ресурсы между внутренними заданиями.  Эти и похожие частные задачи в комплексе решаются в нашем программном обеспечении. Однако, обработка потока данных в реальном времени — не единственное применение наших приложений.  Второй вид программ, которые мы создаём, — это сервисы. Например, получив от нашей лаборатории больших данных и статистики модель, мы обеспечиваем вокруг неё сервис, который отвечает на клиентские запросы. Например, они присылают нам записанный звук, а в ответ получают распознанную речь в виде текста. Таких клиентов могут быть десятки, сотни и тысячи одновременно. С распределением их запросов между разными экземплярами модели и возвратом результатов обработки, собственно, и справляется наш софт. То есть это мощный backend, балансирующий внешнюю нагрузку между доступными внутренними ресурсами. — Сейчас вы используете для облачных вычислений графические процессоры? — Конечно! В половине наших разработок приходится использовать CUDA-библиотеки, чтобы передавать пакеты подготовленных специальным образом данных для моделей и забирать оттуда результаты. — Вы на OpenCL пробовали что-то делать? — Сейчас мы работаем только с инфраструктурой Nvidia. В дальнейшем планируем диверсифицироваться по разным технологиям, включая OpenCL. — Какими программами вы пользуетесь для совместной работы, какой стек технологий используете? — Для совместной работы в компании используется GitLab — в разработке, Confluence — в более общих областях. Мы пользуемся общим инструментарием: так удобнее взаимодействовать с другими командами и руководством. Технологический стек также определяется для отдела разработки в целом, с учётом общих задач: OpenShift, Kafka, Clickhouse, Scylla и т.д. Что касается инструментов собственно разработки, то в Rust есть де-факто стандарт: cargo + rust-analyzer + некоторый выбор IDE, например, VSCode, IntelliJ, CLion, Neovim, Emacs. — Что ещё должен знать Rust-разработчик для эффективной работы над реальными проектами? — Мы создаём довольно сложный софт, работающий в условиях:  высоких нагрузок по потоку данных; недопустимости потерь при обработке данных; длительной работы во времени, месяцами без перезапуска; использования всех доступных вычислительных мощностей; задействования и обмена данными с GPU; отсутствия интерфейса пользователя. Поэтому мы используем проверенные временем сторонние решения отдельных задач, например, для буферизации данных, хранения результатов, мониторинга состояния.  С нашими сервисами взаимодействует другой софт на общей платформе, поэтому нужно понимание принципов и технологий такого взаимодействия. Чем шире у разработчика знания в использовании принятого у нас технологического стека, тем более эффективно он работает. С точки зрения программирования, помимо знания самого языка, создание качественного софта требует навыков профилировки и написания бенчмарков, опыта в использовании CI, развёртывания в Openshift, работы с докером и пр. — Почему твой выбор пал на Rust? Каковы особенности разработки на этом языке? — Я пропагандирую коллегам переход на Rust:) он превосходит С++ по выразительности: код с одинаковой функциональностью в разы короче на Rust; не уступает C++ по производительности итогового приложения; компилятор даёт существенные гарантии надёжности кода и безопасности работы с памятью, одной из основных проблем в системном и серверном софте; цикл разработки существенно короче (написать код — примерно 80% готовности, оставшиеся 20% — отладка приложения, как правило, логики); огромное количество библиотек и фреймворков для любых областей написано на Rust; совместим с наследием на С++.  — Какие языки программирования являются лучшей базой для перехода на Rust? — Компилируемые языки без среды исполнения и механизмов сборки мусора с поддержкой шаблонного программирования и полиморфизма. Получается, это С++. — У тебя в команде все бывшие «сишники»? — Нет, не все. Есть те, кто писал на Go, Haskell и Java. Почему «Rust – не Си на стероидах» читайте в интервью с ведущим системным программистом департамента разработки компании «Криптонит» Михаилом Дорониным. — То есть с Haskell вполне можно перейти на Rust?  — Да. На самом деле Rust не Си-подобный. Когда вижу конструкции на Scala/Haskell или программу на Go, мне кажется, что команда, которая проектировала Rust, старалась взять лучшее из разных языков. Соответственно, программист, знающий Scala, Haskell или Go, увидит что-то близкое, понятное ему. Но программисту с опытом работы на С++ меньше других придётся подстраиваться под ограничения, которые другим на начальном этапе кажутся непривычными.  В общем, на Rust можно перейти хоть с C#. Но надо понимать, что меняется концепция: отсутствует среда исполнения, автоматическое управление памятью. И тебе придётся заботиться о том, о чём ты заботиться не привык. — Думать, как код внутри исполняется? — Да. И понимать, к чему каждая твоя строчка кода приводит на машинном уровне. — То есть отвыкать от мысли, что компилятор всю внутреннюю кухню сделает за тебя. — На других языках — да. А для разработчика на С++, наоборот. Компилятор какие-то вещи, о которых ты раньше должен был думать сам, берёт на себя и запрещает тебе сделать то, что потенциально может привести к созданию ненадёжной или аварийной программы. — Как началось твоё знакомство с Rust? — С книги «Программирование на языке Rust». Мы её называли «книга с крабиком» :) Она вышла в издательстве O'Reilly, была переведена у нас, и, по-моему, была такая первая и единственная. Удачной эта книга была потому, что её авторы как будто, также, как и я, до Rust работали на C++. Их аналогии и поясняющие примеры построены на сравнении этих языков. Разработчику на С++ она очень подходит. — Ты учился только по книге?  — Да. Мне сперва надо понять правила игры, а потом их на чём-то попробовать. На проекте по выпуску блокчейна я написал наше программное обеспечение на Rust, и в процессе самостоятельно проходил все привычные для программиста пути: и пользовался советами Stack Overflow, и возвращался к учебнику, и смотрел каталоги библиотек, которые есть на Rust, и экспериментировал. Но, чтобы никого не напугать, напоминаю, что есть и обучающие курсы.  — Поделись полезными материалами и ресурсами для Rust-разработчиков. — Могу рекомендовать серию видео с погружением в отдельные темы от Jon Gjengset https://www.youtube.com/@jonhoo. В них вполне понятный английский, глубокий уровень погружения в выбранную тему и увлекательный стиль изложения. Есть ещё интересный ресурс https://cheats.rs. Этот ресурс больше всего похож на удобный набор «шпаргалок» по Rust, очень наглядных, с полезными советами и готовыми примерами.  P.S. Дополнительные полезные материалы смотрите также в нашем полном обзоре языка программирования Rust. В статье рассказываем о его особенностях, применении, плюсах и минусах.