Мы побеседовали с руководителем направления системного программирования в «Криптоните» Александром Авраменко о карьерном пути Rust-разработчика, особенностях языка Rust и его применении к моделям машинного обучения в высоконагруженных системах.
![](https://habrastorage.org/getpro/habr/upload_files/665/623/f41/665623f418129798e3dfc9a41ac68d2d.jpg)
— Александр, расскажи о своём карьерном пути.
— Я учился в МАИ, получил диплом с отличием по специальности «бортовые системы». Всегда любил вычислительную технику и программирование. Уже в те времена был язык С, на котором я помогал писать пользовательские интерфейсы, заготовки для лабораторного САПРа и т.д.
Затем работал в ОКБ Сухого, делал ПО лётного тренажёра. В «живой» кабине с вмонтированными экранами подключался наш софт. Мы визуализировали облака, землю, аэродромы, рисовали карты, план полёта, индикаторы...
Потом я перешёл работать в блокчейн как в очень перспективную и технологически интересную область. Этот проект тоже был доведён до продакшена — мы запустили главную сеть. Как раз тогда, примерно в 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. В статье рассказываем о его особенностях, применении, плюсах и минусах.