Rust jako first-class citizen w ekosystemie Elixira - jak Rustler zmienia zasady gry
Jest takie powiedzenie w świecie Elixira: "Jeśli BEAM jest za wolny na Twój problem, to Twój problem jest naprawdę ciekawy." BEAM obsługuje miliony połączeń, przetwarza wiadomości w mikrosekundach, utrzymuje systemy telekomunikacyjne z uptime 99.9999999%. Ale jest klasa problemów, na które potrzebujesz czegoś bliżej metalu. I tu wchodzi Rust.
Nie jako zamiennik. Nie jako konkurencja. Jako partner.
Czym jest Rust (dla tych, którzy jeszcze nie wiedzą)
Rust to język systemowy stworzony przez Mozillę, rozwijany od 2015 roku jako open source. Przez 8 lat z rzędu wygrywał ankietę Stack Overflow jako "najbardziej kochany język programowania". Nie bez powodu.
Wydajność na poziomie C/C++
Rust kompiluje się do natywnego kodu maszynowego. Nie ma garbage collectora, nie ma runtime'u, nie ma wirtualnej maszyny. Kod Rust działa tak szybko, jak pozwala na to sprzęt. W benchmarkach regularnie dorównuje C i C++ - a często je wyprzedza dzięki agresywnym optymalizacjom kompilatora LLVM.
Bezpieczeństwo pamięci bez garbage collectora
To rewolucja, którą Rust wniósł do programowania systemowego. Borrow checker - system typów wbudowany w kompilator - gwarantuje w czasie kompilacji, że:
- Nie ma wiszących wskaźników (use-after-free)
- Nie ma podwójnego zwalniania pamięci (double free)
- Nie ma wyścigów danych (data races)
- Nie ma przepełnień bufora (buffer overflows)
Microsoft szacuje, że 70% podatności bezpieczeństwa w ich produktach to błędy pamięci. Google raportuje podobne liczby dla Chromium. Rust eliminuje całą tę klasę problemów. Nie łagodzi, nie łapie w runtime - uniemożliwia na poziomie kompilatora.
Kto używa Rust w produkcji
To nie jest język akademicki. Rust napędza krytyczną infrastrukturę:
- Linux kernel - Rust jest drugim oficjalnym językiem jądra Linuxa (od wersji 6.1)
- Android - Google przepisał krytyczne komponenty Androida na Rust, redukując podatności pamięci o 68%
- AWS - Firecracker (silnik Lambda i Fargate), Bottlerocket OS, S2N-TLS
- Cloudflare - Pingora, proxy obsługujący ~40% ruchu internetowego, przepisany z C na Rust
- Discord - przepisali serwis Read States z Go na Rust, redukując latencję z 50ms na 1ms przy 10x mniejszym zużyciu RAM
- Meta - Rust w backendzie Facebooka do obsługi source control (Mononoke)
- Microsoft - coraz więcej komponentów Windows w Rust, Azure IoT Edge
- Dropbox - silnik synchronizacji plików przepisany z Pythona na Rust
Problem: BEAM jest genialny, ale nie do wszystkiego
BEAM jest zoptymalizowany pod współbieżność i niezawodność - obsługę milionów lekkich procesów, message passing, hot code reload. To platforma do budowy systemów rozproszonych.
Ale BEAM nie jest zoptymalizowany pod surowe obliczenia numeryczne. I to jest OK - nie do tego został zaprojektowany. Oto klasa problemów, gdzie BEAM jest za wolny:
- Kryptografia - hashowanie haseł, szyfrowanie, weryfikacja podpisów
- Parsowanie binarnych protokołów - dekodowanie plików, przetwarzanie obrazów, analiza pakietów sieciowych
- Serializacja/deserializacja - JSON, MessagePack, Protocol Buffers przy dużych wolumenach
- Obliczenia numeryczne - machine learning, statystyka, przetwarzanie sygnałów
- Kompresja/dekompresja - gzip, zstd, brotli na dużych zbiorach danych
- Operacje na stringach - regex na gigabajtowych logach, przetwarzanie tekstu
Tradycyjne rozwiązanie? Napisz to w C jako NIF (Native Implemented Function) i wywołaj z Erlanga. Problem: C nie ma gwarancji bezpieczeństwa pamięci. Błąd w C NIF-ie może zawalić całą maszynę wirtualną BEAM. Jeden segfault - i tracisz wszystkie procesy, wszystkie połączenia, cały system. To zaprzeczenie filozofii "let it crash".
Rustler - most między dwoma światami
Rustler to biblioteka Elixira, która pozwala pisać NIF-y w Rust zamiast w C. I to zmienia wszystko.
Jak to działa
Tworzysz zwykły projekt Elixira. Dodajesz zależność Rustler. Piszesz funkcję w Rust. Wywołujesz ją z Elixira jak normalną funkcję Elixira. Koniec.
# W Elixirze - wywołanie wygląda jak zwykła funkcja
defmodule MojSystem.Crypto do
use Rustler, otp_app: :moj_system, crate: "moj_crypto"
# Funkcja zaimplementowana w Rust
def hash_password(_password, _salt), do: :erlang.nif_error(:nif_not_loaded)
def verify_signature(_data, _signature, _key), do: :erlang.nif_error(:nif_not_loaded)
end// W Rust - czysta logika, zero boilerplate'u
#[rustler::nif]
fn hash_password(password: String, salt: String) -> String {
argon2::hash_encoded(password.as_bytes(), salt.as_bytes(), &Config::default())
.unwrap()
}
#[rustler::nif]
fn verify_signature(data: Binary, signature: Binary, key: Binary) -> bool {
let public_key = PublicKey::from_bytes(key.as_slice()).unwrap();
public_key.verify(data.as_slice(), &Signature::from_bytes(signature.as_slice()).unwrap())
.is_ok()
}Żadnych wrapperów, żadnych serializacji, żadnych FFI bindings do ręcznego pisania. Rustler automatycznie konwertuje typy Elixira na typy Rust i z powrotem. Binaries, listy, mapy, struktury - wszystko działa.
Bezpieczeństwo BEAM zostaje nienaruszone
To kluczowa różnica między NIF-em w C a NIF-em w Rust:
NIF w C: Błąd w kodzie C (buffer overflow, null pointer dereference, use-after-free) = crash całego BEAM VM. Wszystkie procesy, wszystkie połączenia, cały system - martwy. Nie ma supervisor tree, które to uratuje.
NIF w Rust: Borrow checker gwarantuje, że te błędy nie mogą wystąpić. Kod się nie skompiluje, jeśli zawiera potencjalne naruszenie pamięci. BEAM jest bezpieczny, bo Rust jest bezpieczny.
Oczywiście, Rust pozwala na unsafe bloki - ale to jest jawna, świadoma decyzja programisty, nie przypadkowy bug. W praktyce 99% NIF-ów w Rust nie potrzebuje unsafe.
Dirty schedulers - bez blokowania BEAM
BEAM ma ścisłe zasady dotyczące NIF-ów: funkcja NIF nie powinna działać dłużej niż 1 milisekundę, bo blokuje scheduler i spowalnia inne procesy. Rustler integruje się z mechanizmem dirty schedulers BEAM, który pozwala uruchamiać długotrwałe NIF-y na dedykowanych wątkach - bez wpływu na resztę systemu.
Hashowanie hasła trwa 200ms? Żaden problem. Przetwarzanie obrazu trwa 2 sekundy? Idzie na dirty scheduler. Reszta BEAM nawet nie zauważy.
Realne zastosowania Rust + BEAM
Przetwarzanie danych w systemach ERP
Klient importuje katalog produktów - 500 000 pozycji w CSV. W czystym Elixirze parsowanie i walidacja trwa 45 sekund. Po przepisaniu parsera CSV na Rust przez Rustler - 800 milisekund. 56x szybciej. Użytkownik klika "Importuj" i nie zdąży nalać kawy, zanim system skończy.
Kryptografia i bezpieczeństwo
Hashowanie haseł z Argon2, weryfikacja tokenów JWT, szyfrowanie danych wrażliwych - to operacje, które w Elixirze są "wystarczająco szybkie" dla pojedynczych żądań, ale przy tysiącach jednoczesnych logowań stają się wąskim gardłem. Rust NIF obsługuje tę samą operację 10-50x szybciej, zwalniając zasoby BEAM na to, w czym jest najlepszy - współbieżność.
Generowanie PDF-ów
Faktury, raporty, etykiety. Generowanie PDF-a z szablonu w Elixirze jest możliwe, ale wolne. Rust z biblioteką printpdf lub genpdf generuje dokumenty wielokrotnie szybciej. W systemie ERP, który wystawia 1000 faktur dziennie, to różnica między "generator PDF blokuje system" a "PDF gotowy w tle, zanim użytkownik kliknie Pobierz".
Walidacja i transformacja danych
Reguły biznesowe w ERP bywają złożone: "cena produktu zależy od kategorii klienta, grupy rabatowej, daty, minimalne zamówienie, waluta, region, a do tego 47 wyjątków historycznych". Silnik reguł napisany w Rust przetwarza te walidacje na dużych zbiorach danych o rząd wielkości szybciej niż w Elixirze.
Przetwarzanie obrazów
Miniaturki produktów, watermarki, konwersja formatów. Biblioteka image w Rust jest jedną z najszybszych na rynku. Przez Rustler - wywoływana jedną linijką z Elixira.
Dlaczego nie po prostu "wszystko w Rust"?
Dobre pytanie. Jeśli Rust jest taki szybki, to po co BEAM?
Bo Rust nie ma tego, co ma BEAM:
| Cecha | Rust | BEAM (Elixir) |
|---|---|---|
| Surowa wydajność CPU | Ekstremalnie szybki | Wolniejszy 10-100x w obliczeniach |
| Współbieżność | Trzeba zarządzać ręcznie (tokio, async) | Miliony procesów out of the box |
| Odporność na awarie | Panic = crash procesu OS | Let it crash + supervisor restart |
| Hot code reload | Nie ma (restart wymagany) | Aktualizacja bez downtime'u |
| WebSocket / real-time | Trzeba budować od zera | Phoenix Channels / LiveView |
| Czas developmentu | Dłuższy (borrow checker wymaga nauki) | Szybki prototyping, szybkie iteracje |
| Dystrybucja | Trzeba budować od zera | Wbudowana w BEAM (clustering) |
Rust jest jak silnik Ferrari - potężny, precyzyjny, wymagający. BEAM jest jak kolej - niezawodny, skalowalny, obsługujący miliony pasażerów jednocześnie. Nie budujesz kolei z silników Ferrari. Ale Ferrari w pociągu ekspresowym - to ma sens.
Ekosystem: Rust w świecie Elixira to nie hack
Integracja Rust + Elixir to nie obejście. To świadomy, wspierany przez społeczność kierunek rozwoju. Dowody:
Rustler - dojrzały i stabilny
Rustler istnieje od 2017 roku, jest aktywnie rozwijany, ma ponad 4000 gwiazdek na GitHubie. Używany w produkcji przez dziesiątki firm. Dokumentacja jest kompletna, community aktywne.
Explorer - Rust pod spodem Elixira
Explorer to biblioteka do analizy danych w Elixirze (odpowiednik Pandas z Pythona). Pod spodem używa Polars - silnika napisanego w Rust. Interfejs jest czystym Elixirem, wydajność jest jak w Rust. To oficjalna biblioteka w ekosystemie Nx (Numerical Elixir).
Nx i Livebook
Nx (Numerical Elixir) to framework do machine learning w Elixirze. Kompiluje operacje tensorowe do natywnego kodu przez EXLA (Google XLA) lub Torchx (LibTorch). Rust jest fundamentem wielu komponentów tego ekosystemu.
Jason - najszybszy parser JSON
Jason, domyślny parser JSON w Phoenix, jest napisany w Elixirze. Ale gdy potrzebujesz jeszcze więcej wydajności, jest jsonrs - wrapper na serde_json z Rust. Drop-in replacement, 2-5x szybszy.
ExWebRTC
Implementacja WebRTC w Elixirze, z krytycznymi komponentami (kodeki, przetwarzanie mediów) w Rust. Real-time video w Phoenix, z wydajnością Rust w przetwarzaniu strumieni.
Wybór technologii dla naszych aplikacji to nie przypadek
Nasza firma łączy Rust i Erlang (platformę, na której działa Elixir) nie tylko w nazwie. To nasza filozofia architektoniczna:
- Logika biznesowa, współbieżność, real-time → Elixir na BEAM
- Wydajność krytyczna, przetwarzanie danych, kryptografia → Rust przez Rustler
- Baza danych → PostgreSQL
Te trzy technologie nie konkurują ze sobą. Każda robi to, w czym jest najlepsza. Razem tworzą stack, który jest jednocześnie niezawodny (BEAM), wydajny (Rust) i sprawdzony (PostgreSQL).
To nie kompromis. To synergia.
Budujesz system, który musi być jednocześnie szybki i niezawodny? Porozmawiajmy - pokażemy, jak Rust i Elixir mogą współpracować w Twoim projekcie.