Présentation du problème
Le modèle de programmation async/await a gagné la guerre de la concurrence ces dix dernières années en raison de sa facilité d'utilisation. Cependant, sous cette syntaxe familière se cache une complexité structurelle massive qui cache le contrôle du flux, obscurcit les réalités matérielles et repousse la charge de planification sur le développeur.
Le piège de la concurrence
Le piège fondamental d'async/await est qu'il confond l'asynchronisme (céder la main pendant l'attente d'entrées-sorties) avec la concurrence (traiter plusieurs choses à la fois). La syntaxe est un piège car elle déguise les machines d'état entrelacées en threads séquentiels isolés. Les développeurs écrivent des fonctions asynchrones exactement comme du code bloquant, mais sans tenir compte des tâches gourmandes en CPU qui peuvent bloquer l'exécution de l'ensemble du thread.
Limites et risques
Lorsque les pics de latence se produisent, la solution est toujours la même : séparer les runtime. Utiliser Tokio pour les entrées-sorties et envoyer les tâches gourmandes en CPU à un pool de threads dédié comme Rayon. Cependant, cela conduit à des complexités et des risques supplémentaires, tels que la nécessité de partitionner manuellement les tâches et de gérer les frontières entre les différents runtime.
Alternatives et solutions
Une alternative à async/await est de concevoir un framework de concurrence qui expose les machines d'état et donne aux utilisateurs un meilleur contrôle sur les primitives de concurrence. Le projet Tina est un exemple de tel framework, qui impose des contraintes strictes pour garantir un débit élevé et une fiabilité massive. Il utilise un modèle de concurrence partagé-rien, avec des threads par cœur, et des communications entre les cœurs via un sous-système de messagerie.