Google, Facebook та Amazon вже пишуть на Rust. Що це за мова і які її перспективи?
Мене звати Валентин Файчук, я працюю Software Engineer в компанії SoftServe у проекті з кібербезпеки. Займаюся розробкою платформи для підтримки різних хмарних security-сервісів. Основний фреймворк проєкту написаний на С, однак у доповнення команда вирішила використати Rust.
Швидкість чи надійність? Багатьом програмістам часто доводиться вирішувати, що важливіше, обираючи мову програмування. Перед таким вибором постав і Грейдон Хор. Він подумав, а чому б не поєднати швидкість і широкі можливості С++ та надійність Haskell? Так у 2015 з’явилася мова Rust, яка вже п’ять років поспіль є улюбленою мовою програмістів за версією StackOverflow.
Ця стаття буде цікава тим, хто хоче або уже почав писати на Rust. У ній я розповім, чому наша команда вирішила перейти на цю мову програмування, як її використовувати на практиці, та за що Rust люблять і критикують.
Що особливого в Rust
Rust — це універсальна мова програмування, яку розробляє компанія Mozilla. Вона позиціонується як:
- компільована (готову програму можна запустити на будь-якому комп’ютері, який сумісний з версією програми);
- системна (нею пишуть програми для роботи систем, адже вона надає високий рівень контролю над функціями заліза);
- мультипарадигмальна (в ній поєднуються кілька парадигм програмування: С++ і Haskell).
Rust вирішує проблеми, що мучили C/C++ розробників довгий час: помилки пам’яті та багатопотокове програмування. По-перше, тут немає збирача сміття. Rust керує пам’яттю через систему володіння з набором правил, які компілятор перевіряє під час компіляції. Як тільки компілятор бачить, що певна змінна вже не буде використовуватися, він автоматично передає виокремлену під неї памʼять для інших цілей.
Інша особливість Rust — це паралельне програмування. У паралельного коду можуть бути небажані взаємодії між потоками, включно з дедлоками (deadlock), конкуренцією та дата рейсами (data races). Rust використовує концепцію володіння і запозичення. Якщо ви присвоюєте блоку даних іншу змінну, то попереднє присвоєння втратить доступ. Тобто, у кожної змінної є унікальний власник, а право володіння можна передати чи позичити. Так, система складна, але таким чином в Rust досягається memory safety.
Також в Rust немає наслідування класів, адже вона не є класичною об’єктно орієнтованою мовою. Можна наслідувати інтерфейси (traits), але це не можна назвати повноцінним наслідуванням.
Мова, яку люблять і бояться
Rust — це молода мова, яка швидко стала популярною серед програмістів. Основна її перевага у тому, що вона сильно оптимізується компілятором і водночас має високий рівень безпеки. Тому незважаючи на те, що основний фреймворк на нашому проекті написаний на С, ми вирішили використовувати Rust через її безпечність. Вона має автоматичний хендлінг дуже багатьох кейсів, але по продуктивності дозволяє досягти майже такого ж рівня, що й С.
Водночас, у Rust є два режими роботи: safe i unsafe. У першому є деякі обмеження, наприклад, object ownership management, щоб забезпечити належну роботу коду. В unsafe {} режимі вам відкриваються всі можливості, але ви не застраховані від поломок.
Ще один плюс цієї мови в тому, що вона дозволяє використовувати дуже багато трюків з C. Наприклад, асемблерні вставки, SIMD — різні хитрі інструкції, які дозволяють працювати з хардварними механізмами. Зазвичай різними такими хаками відомі низькорівневі мови, такі як С, але при цьому вони є в Rust.
Особливо мені подобається робота з перелічуваними типами даних (enumerations). Вони можуть мати кілька варіантів значення і ці варіанти можуть мати свій аргумент. Наприклад, перший варіант — None (немає значення), другий — U32, який має змінну формату U32 в собі, що дозволяє витягнути потрібне. В U64, відповідно, буде змінна більшого розміру. Rust це все робить як об’єднання (unions, спеціальний тип даних в С, що дозволяє зберігати різні типи даних в одній області пам’яті). Тобто вони всі накладаються один на одного, і на початку є Bid, що каже, який саме варіант зараз активний.
Серед мінусів Rust — перевикористання бібліотек на С, які за замовчуванням, грубо кажучи, вважаються unsafe. З одного боку, вони перевірені часом, а з іншого — ти ніколи не знаєш, де там може ховатися баг. Також через те, що Rust перевіряє більше елементів і сама собою є розумнішою, вона довше компілює код — загалом, в
Мова Rust — класна, але їй бракує формальної специфікації. Це, напевне, є визначальним фактором, чому деякі проекти побоюються її використовувати. Та попри це, в Rust є величезна та дружня ком’юніті, яка активно його розвиває. Ба більше, Rust рухається в напрямку створення специфікації та має офіційну базу RFCs (Request For Change). Тому, думаю, в найближчому майбутньому цю мову зможуть застосовувати у більшій кількості сфер.
Як вивчити цю мову? Спойлер: наберіться терпіння
Я відкрив для себе Rust рік тому, коли перейшов на мій теперішній проєкт. За цей час ми з командою спробували різні тулчейни. Починали з stable rust та clang-11. З часом перейшли на clang-12, оскільки навесні Rust перевів свої тулчейни (stable та nightly) на нову версію; та nightly rust, бо там доступні «не стабільні (на деяких платформах)» інтрінсіки (intrinsics). Вони дозволяють нам отримати перформанс коду рівня таких низькорівневих мов як C. Сьогодні ми продовжуємо активно розвивати Rust-напрямок в нашій компанії, наприклад, зараз його вчить група в нашій IT Academy.
Але треба бути готовим, що вчитися доведеться довго. На початку ця мова дуже лоскотатиме вам нерви, бо Rust майже нічого не дозволяє. Ти можеш пробувати різні варіанти, а воно не буде компілюватися. Але потім ти втягуєшся, починаєш розуміти, і це дає тобі великий досвід як програмісту. Ось приклад функції, звичайної для інших мов, яку Rust не дозволить скомпілювати:
fn get_ranged_vec(low: usize, high: usize) -> Vec<usize> { let coll = (low..high).collect(); for elem in coll { // coll is moved (consumed) here print!("{}, ", elem); } coll // <- won’t compile, coll is unknown }
Справа в тому, що Rust-змінні існують тільки в межах свого скоупу і до моменту, поки їх не перемістити в інший скоуп. Ми називаємо цей процес «споживання змінної одного скоупу іншим». В цьому прикладі змінна coll була переміщена в тіло циклу for, відтак спожита із скоупу функції. Для виправлення помилки, наприклад, можна перемістити в цикл не саму змінну, а посилання на неї &coll.
fn get_ranged_vec(low: usize, high: usize) -> Vec<usize> { let coll = (low..high).collect(); for elem in &coll { // reference coll instead of consuming print!("{}, ", elem); } coll // coll is moved here - consumed by the scope of caller }
Я вчив Rust, одночасно читаючи книгу Джима Бленді «Programming Rust» та практикуючись. Часто після прочитаного абзацу чи знайденої нової фічі в інтернеті доводилось повертатись до вже написаного коду. Зрештою, тут не існує чіту з назвою «rust-in-15-mins.txt», прочитавши який, програміст може сказати, що вміє на ньому девелопити (якщо знайдете такий — не вірте).
Особисто мені найскладніше давався концепт позичання змінних (borrowing & mut borrowing). Основний лайфхак, як підходити до таких комплексних концептів — це читати, пробувати, читати ще більше, і тоді все вийде. Початківцям раджу переглянути цей ресурс, а досвідченим розробникам систем на C/C++ для швидкого старту допоможуть матеріали за посиланням.
Google, Facebook, Amazon... Де використовують Rust?
Мова Rust досить універсальна і підходить для різних задач: розробки операційних систем, веб-серверів, інфраструктури, сервісів для управління криптографічними ключами та інших. Однак з Rust є певні обмеження, адже вона не має офіційної ліцензійної документації, тому її не можна використовувати в дуже відповідальних сферах, як от авіаконструювання. Але сподіваємося, що оскільки ця мова постійно розвивається та оновлюється, скоро це зміниться.
Rust повним ходом використовують технічні гіганти. Facebook навесні приєднався до Rust Foundation, поруч з Amazon Web Services, Google, Huawei, Microsoft та Mozilla. Компанія пише на Rust ще з 2016 року, зокрема його використовували у криптовалютному проекті Libra, для сервера управління версіями Mononoke тощо. У Facebook кажуть, що після переходу Mononoke з C++ на Rust багато JavaScript i Python девелоперів зацікавилися цією мовою програмування через високий перфоманс і виявлення помилок під час компіляції.
Механізм синхронізації з зовнішнім сховищем даних (sync engine) Dropbox також написаний на Rust. За їхніми словами, його оцінили через перфоманс, ергономічність та сфокусованість на коректності. А Google планує використати Rust як другу мову програмування для ядра Linux. Крім того, техгігант також допускав можливість, що цю мову використають в Android Open Source Project, аби зменшити кількість багів з memory safety.
Серед інших компаній, які використовують Rust у своїх проектах, — Atlassian, Evo Company, Coursera, Cryptape та інші.
Підіб’ємо підсумки
Отже, чи варто братися за Rust? Якщо ви шукаєте мову з високим перфомансом, сек’юрністю та ергономічністю, то так. Rust має надійну систему взаємодії з пам’яттю, потужний аналізатор коду, який дозволяє уникати помилок, С-подібний синтаксис та інші переваги. Але будьте готові до того, що вчитися доведеться довго і важко.
Rust — це cutting edge language, тобто вона має всі властивості мови сучасності, бо С уже досить олдскульна. Наші клієнти це також усвідомлюють і хочуть в майбутньому використовувати нові підходи у своїх проєктах. Поки що розробників, які пишуть цією мовою, не так багато, що робить таких кандидатів дуже цінними. Американська компанія O’Reilly провела опитування серед понад 3000 своїх підписників у США, і виявилося, що найбільше заробляють Rust-розробники — $180 000 на рік. Python-розробники мають $150 тисяч. Тому, на мою думку, це дуже перспективна мова.
216 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів