- In der Rust-Community sieht man häufig die Frage: Wenn Threads alles können, was
async/await kann, und dazu noch einfacher sind, warum entscheidet man sich dann für async/await?
- Rust ist eine Low-Level-Sprache und verbirgt die Komplexität von Coroutines nicht. Das ist das Gegenstück zu Sprachen wie Go, die standardmäßig asynchron arbeiten, ohne dass Programmierer Asynchronität überhaupt berücksichtigen müssen.
- Clevere Programmierer versuchen, Komplexität zu vermeiden — warum also braucht man
async/await?
Den Hintergrund verstehen
- Rust ist eine Low-Level-Sprache. Code ist normalerweise linear: Wenn eine Aufgabe endet, wird die nächste ausgeführt.
- Wenn jedoch viele Aufgaben gleichzeitig ausgeführt werden müssen, etwa in einem Webserver, wird linearer Code zum Problem.
- Das frühe Web versuchte, dieses Problem durch die Einführung von Threading zu lösen.
- Mit Threads lassen sich mehrere Clients gleichzeitig bedienen, doch Programmierer wollten Nebenläufigkeit aus dem OS-Space in den User-Space holen.
Das Timeout-Problem
- Einer der größten Vorteile von Rust ist die Komponierbarkeit (composability).
async/await ermöglicht es, diese Komponierbarkeit auch auf I/O-gebundene Funktionen anzuwenden.
- Wenn man zum Beispiel einer Client-Handler-Funktion ein Timeout hinzufügen möchte, lässt sich das mit zwei Combinators umsetzen.
Thematische Threads
- In einem Beispiel auf Basis von Threads ist ein Timeout nicht leicht umzusetzen.
TcpStream hat zwar die Funktionen set_read_timeout und set_write_timeout, ihre Verwendung ist aber eingeschränkt.
- Es wird gezeigt, wie sich Timeouts mit Rust-Combinators programmieren lassen, doch das ist auf
TcpStream beschränkt und erfordert zusätzliche Systemaufrufe.
Erfolgsbeispiele für Async
- Das HTTP-Ökosystem hat
async/await als zentralen Runtime-Mechanismus übernommen.
tower ist ein Beispiel für die Stärke von async/await und bietet Timeouts, Rate Limiting, Load Balancing und mehr.
macroquad ist eine Rust-Game-Engine, die ihre Engine mit async/await ausführt.
Das Image von Async verbessern
- Die Vorteile von
async sind nicht allgemein bekannt, weshalb manche Menschen sie missverstehen können.
- Die Rust-Community neigt dazu, die Performance-Vorteile von
async Rust zu überschätzen und seine eigentlichen, bedeutenden Vorteile zu kleinzureden.
async/await sollte als starkes Programmiermodell gesehen werden, das Muster prägnant ausdrücken kann, die sich in synchronem Rust ohne Dutzende Threads und Channels nicht formulieren lassen.
Meinung von GN⁺
async/await erhöht beim Umgang mit Nebenläufigkeit zwar die Komplexität des Codes, bietet aber zugleich die Fähigkeit, sehr viele Clients effizient zu bedienen.
- Dieser Artikel betont, dass
async/await nicht nur Vorteile bei der Performance bietet, sondern auch Stärken als Programmiermodell hat.
- Rusts
async/await bietet Komponierbarkeit für verschiedenste I/O-Aufgaben, was besonders in Bereichen wie Netzwerkdiensten oder Webservern nützlich ist.
- Kritisch betrachtet kann die Komplexität von
async/await für Einsteiger eine Einstiegshürde sein, weshalb Bildungs- und Vermittlungsarbeit nötig ist.
- Andere Projekte mit ähnlicher Funktionalität sind etwa die
async/await-Implementierung von Node.js oder die asyncio-Bibliothek von Python, die ein ähnliches Paradigma bieten.
- Bei der Einführung von
async/await sollten die Komplexität des Codes und die Wartbarkeit berücksichtigt werden; wenn jedoch viele Clients gleichzeitig verarbeitet werden müssen, bietet dieses Modell große Vorteile.
1 Kommentare
Hacker-News-Kommentare
Async/await und Single-Threading
Mutexund die Kanäle voncrossbeam-channelsind unfair.Async/await vs. Threads
Probleme mit dem Artikel
Nicht behandelte Aspekte
Wichtige Punkte zur Abbruchlogik
Eine marketingartige Kampagne für Async/await
Async/await vs. Fiber
Wichtigste Vorteile von Async/await in Rust
Missverständnisse über Async/await
Warum Async/await statt Threads wählen