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:

CechaRustBEAM (Elixir)
Surowa wydajność CPUEkstremalnie szybkiWolniejszy 10-100x w obliczeniach
WspółbieżnośćTrzeba zarządzać ręcznie (tokio, async)Miliony procesów out of the box
Odporność na awariePanic = crash procesu OSLet it crash + supervisor restart
Hot code reloadNie ma (restart wymagany)Aktualizacja bez downtime'u
WebSocket / real-timeTrzeba budować od zeraPhoenix Channels / LiveView
Czas developmentuDłuższy (borrow checker wymaga nauki)Szybki prototyping, szybkie iteracje
DystrybucjaTrzeba budować od zeraWbudowana 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.