- Vorstellung einer Strategie, um Rust schrittweise zu Nicht-Rust-Servern (JavaScript, Python, Java usw.) hinzuzufügen
- Ziel ist es, Hot Functions zu identifizieren, die aufgrund von CPU-Engpässen die Performance-Anforderungen nicht erfüllen, und sie durch Implementierungen in Rust zu ersetzen
- Die Strategie ist nach Tiers (Grad der Rust-Einführung) gegliedert: Tier 0 verwendet kein Rust, das letzte Tier ist eine vollständige Neuschreibung des gesamten Servers in Rust
Strategie
Tier 0: Kein Rust
- Implementierung eines Endpunkts zur QR-Code-Erzeugung in einem Node.js-Server
- Basisleistung: 1464 Requests pro Sekunde, durchschnittliche Latenz 68 ms, p99-Latenz 96 ms, durchschnittliche Antwortgröße 1506 Byte, Speicher 1353 MB
Tier 1: Rust-CLI-Tool
- Neuschreibung der Funktion zur QR-Code-Erzeugung in Rust und Kompilierung als CLI-Tool
- Aufruf des CLI-Tools vom Host-Server aus
- Performance gegenüber der Basis: 1,76-fach mehr Requests pro Sekunde, durchschnittliche Latenz auf das 0,57-Fache reduziert, durchschnittliche Antwortgröße auf das 0,52-Fache reduziert, Speicher auf das 0,92-Fache reduziert
Tier 2: Rust-Wasm-Modul
- Kompilierung der Rust-Funktion als Wasm-Modul und Laden/Ausführen im Host-Server über eine Wasm-Runtime
- Im Node.js-Server wird
wasm-bindgen verwendet
- Performance gegenüber der Basis: 2,03-fach mehr Requests pro Sekunde, durchschnittliche Latenz auf das 0,50-Fache reduziert
- Erläuterung, wie Wasm-Bindings manuell geschrieben werden können (für Nutzer anderer Sprachen)
Tier 3: Native Rust-Funktion
- Schreiben der Funktion in Rust, Kompilierung zu nativem Code und Laden/Ausführen in der Host-Runtime
- In Node.js wird
napi-rs verwendet
- Performance gegenüber der Basis: 3,75-fach mehr Requests pro Sekunde, durchschnittliche Latenz auf das 0,26-Fache reduziert
Tier 4: Rust-Neuschreibung
- Neuschreibung des gesamten Host-Servers in Rust
- In der Praxis ist es realistischer, nur Teile des Host-Servers neu zu schreiben
- Performance gegenüber der Basis: 4,93-fach mehr Requests pro Sekunde, durchschnittliche Latenz auf das 0,21-Fache reduziert, Speicher auf das 0,01-Fache reduziert (13 MB Verbrauch)
Fazit
- Alle Strategien sind gut, aber Tier 3 ist am effektivsten
- Wenn eine sofort einsetzbare Library zur Erzeugung von Bindings verwendet werden kann, ist das Schreiben nativer Funktionen in Rust einfach und hat großen Einfluss auf die Performance
4 Kommentare
Oh … nachdem ich wie ein Mädchen für alles an verschiedenen Dingen gearbeitet habe, nutze ich inzwischen beide jeweils ein bisschen, und das sind wirklich sehr nützliche Informationen.
Ich habe mir in letzter Zeit Rust angesehen. Ein interessanter Artikel.
Ein ziemlich guter Artikel. So nutzt man Rust richtig.
Offenbar ist Rust inzwischen auch in Bereichen klar beliebt, die man früher mit C/C++ gelöst hat.