- Dans la communauté Rust, on voit souvent revenir la question suivante : les threads peuvent faire tout ce que
async/await peut faire, et plus simplement, alors pourquoi choisir async/await ?
- Rust est un langage de bas niveau qui ne masque pas la complexité des coroutines. C’est l’opposé de langages comme Go, qui deviennent asynchrones par défaut sans que le programmeur ait besoin de penser à l’asynchronisme.
- Les bons programmeurs essaient d’éviter la complexité, alors pourquoi
async/await est-il nécessaire ?
Comprendre le contexte
- Rust est un langage de bas niveau. Le code y est généralement linéaire : une tâche s’exécute une fois la précédente terminée.
- Lorsqu’il faut exécuter de nombreuses tâches en même temps, comme dans un serveur web, le code linéaire pose problème.
- Le web des débuts a tenté de résoudre ce problème en introduisant le threading.
- On peut traiter plusieurs clients simultanément avec des threads, mais les programmeurs ont voulu faire passer la concurrence de l’espace OS à l’espace utilisateur.
Le problème des timeouts
- L’un des plus grands atouts de Rust est sa composabilité.
async/await permet d’appliquer cette composabilité aux fonctions liées aux I/O.
- Par exemple, lorsqu’on veut ajouter un timeout à une fonction de traitement client, on peut l’implémenter avec deux combinateurs.
Threads thématiques
- Dans un exemple utilisant des threads, implémenter un timeout n’est pas simple.
TcpStream propose bien les fonctions set_read_timeout et set_write_timeout, mais leur usage reste limité.
- Une méthode est proposée pour programmer un timeout à l’aide des combinateurs de Rust, mais elle reste limitée à
TcpStream et nécessite des appels système supplémentaires.
Cas de réussite d’async
- L’écosystème HTTP a adopté
async/await comme principal mécanisme d’exécution.
tower illustre bien la puissance de async/await, avec des fonctions comme les timeouts, le rate limiting et l’équilibrage de charge.
macroquad est un moteur de jeu Rust qui exécute son moteur avec async/await.
Améliorer l’image d’async
- Les avantages de
async ne sont pas largement connus, ce qui peut conduire certaines personnes à le mal comprendre.
- La communauté Rust a tendance à surestimer les gains de performance de l’
async Rust et à minimiser ses avantages réellement significatifs.
- Il faut voir
async/await comme un modèle de programmation puissant, capable d’exprimer de façon concise des schémas impossibles à représenter en Rust synchrone sans des dizaines de threads et de canaux.
L’avis de GN⁺
async/await augmente la complexité du code lorsqu’on gère la concurrence, mais apporte en contrepartie la capacité de traiter efficacement un grand nombre de clients simultanément.
- Cet article souligne que
async/await ne se limite pas à des avantages de performance, mais possède aussi de vraies forces comme modèle de programmation.
- Le
async/await de Rust offre de la composabilité pour divers travaux d’I/O, ce qui est particulièrement utile dans des domaines comme les services réseau ou les serveurs web.
- D’un point de vue critique, la complexité de
async/await peut constituer une barrière à l’entrée pour les développeurs débutants, ce qui nécessite un effort pédagogique pour la surmonter.
- Parmi les autres projets offrant des fonctionnalités similaires, on peut citer l’implémentation de
async/await de Node.js ou la bibliothèque asyncio de Python, qui proposent elles aussi un paradigme comparable.
- Lorsqu’on adopte
async/await, il faut prendre en compte la complexité du code et sa maintenabilité ; mais lorsqu’il faut gérer un grand nombre de clients en parallèle, ce modèle apporte de grands avantages.
1 commentaires
Avis Hacker News
Async/await et mono-thread
async/awaiten mono-thread est simple et bien compris.async/awaitmulti-thread est complexe. Dans les sections où le calcul est contraint, le modèle peut s’effondrer.Mutexstandard et les canauxcrossbeam-channelne sont pas équitables.Async/await contre threads
async/await.async/awaitplus composables comme abstractions, ce mécontentement aurait disparu.Problèmes avec l’article
Aspects non abordés
async/awaits’exécute sur un seul thread, donc il n’y a pas besoin de verrous ni de synchronisation.async/awaitn’est pas claire.Point important sur l’annulation
futures.Une campagne façon marketing autour de async/await
async/awaita été une erreur technique et a eu un coût important pour la communauté.Async/await contre fibres
futuresà tout moment entraîne un coût important.async/await.Principaux avantages de async/await en Rust
Malentendus sur async/await
async/awaitest utile pour la programmation d’interface utilisateur, la communication avec le GPU et la communication entre runtimes.Pourquoi choisir async/await plutôt que des threads
async/awaitpeut réduire l’usage mémoire de l’état des clients, des requêtes et des tâches.async/awaitet le CPS sont efficaces pour réduire l’usage mémoire par client.