3 ms·
As an outsider, I often hear about async Rust being less than ideal. Perhaps I don't understand, because I haven't dipped my toes in the water yet... but I do m
by clumsysmurf 3y ago
As an outsider, I often hear about async Rust being less than ideal. Perhaps I don't understand, because I haven't dipped my toes in the water yet... but I do most of my work in Kotlin with Coroutines, and concurrency is everywhere in the UI. I can't imagine working in a language having a major deficit in this space.
Are there any efforts to overhaul or completely rethink this?
- adastra22 3y agoIt’s pretty much the same issue all languages have, that async functions are colored. I don’t think it is unique to rust. Algebraic effects would solve this, but I don’t know any language other than OCaml that is working on that approach.
- adamgordonbell 3y agoCan't scala, haskell, (kotlin?) you just lift functions into Async? You can convert colors simply but only one way, and practically that works, functional core imperative shell, etc.
- subarctic 3y agoI mean... that's not really the pain that people are referring to when they are struggling with async Rust, especially when you compare it other languages like JavaScript that also have a difference between async and regular functions.
- vlovich123 3y agoIt’s not just that. There’s a few big problems with Rust async aside from the normal coloring problem that is inherent to async and not worth talking about. * The async runtime and async functions are decomposed but tightly coupled. That means while you could swap out runtimes, a crate built against one runtime can’t generally be used with another unless explicitly designed to support multiple. I believe C++ has a similar problem but no other major language I’m aware of has this problem - that’s typically because there’s only a single runtime and it’s embedded in the language. Things like timers and I/O are not interoperable because the API you use has to be for the runtime you’re running under. I believe there’s work ongoing to try to remedy this although in practice I think that’s difficult (eg what if you’re using a crate relying on epoll-based APIs but the runtime is io_uring). * async in traits. I believe that’s coming this year although the extra boxing it forces to make that work makes that not something 0-cost you can adopt in a super hot path. * async requires pinned types which makes things very complex to manage and is a uniquely Rust concept (in fact I read a conceptually better alternative proposal for how to have solved the pin/unpin problem on HN not too long ago, but that ship has long sailed I fear). * The borrow checker doesn’t know if your async function is running on a work stealing runtime or not which means there’s a lot more hoop jumping via unsafe if you want optimal performance. * async functions are lazy and require polling before they do anything. That can be a bit surprising and require weird patterns. Don’t get me wrong. The effing-mad crate is a fantastic demonstration of the power of algebraic effects to comprehensively solve coloring issues (async, failability, etc). But I think there’s stuff with runtime interop that’s also important. I don’t think anyone is yet seriously tackling improving the borrow checker for thread per core async.
- Alyan 3y agoAsync in traits feature doesn’t use boxing (which is coming in 28 December), only async-trait crate use boxing.
- vlovich123 3y agoReally? When I read the GitHub issue it seemed like even the standardized implementation results in boxing…
- fwip 3y agoUnison [1] has algebraic effects as a first-class feature. They call them "abilities" there. You can make async about as transparent/opaque as you want it. Docs on abilities in [2]. [1]: https://www.unison-lang.org/ https://www.unison-lang.org/ [2]: https://www.unison-lang.org/learn/language-reference/abilities-and-ability-handlers/ https://www.unison-lang.org/learn/language-reference/abiliti...
- subarctic 3y agoThere's efforts to overhaul it, basically there's a lot of stuff that has to be more complicated (as you'd expect) if you want to add support for async somewhere, and understanding the error messages can be pretty mentally taxing when you get it wrong; and then there's a lot of cases where the async version of some pattern just doesn't work right now due to limitations in the compiler or the language itself, and hopefully it'll work someday, but in the meantime you need to use workarounds.
- myaccountonhn 3y agoFor me I am working on a side project in Rust and had very few issues, Rust felt quite straight forward up until the point where I had to mess around with async. For my domain I need to use a framework that expects you to set up a shared mutable state for the connection pooling in an opinionated way. Suddenly I encountered arc and mutex and very cryptic trait error messages for code doing way too much magic. All I wanted was to share a SQLite connection in an ugly way to get my mvp out but I was dealing with absolutely incomprehensible trait issues. In general I’ve noticed that there are a lot of code generation modules that can generate very cryptic error messages if you stay clear of their happy paths.
- tayo42 3y agoYou would run into the same issues if you tried to do it with threads and rust too. Any kind of shared resource is a tedious experience, that's basically it's selling point. It is frustrating becasue if you go look for help, people are always condescending about global shared resources like that but there really isn't a better way.
- tialaramex 3y agoHere's a better explanation by somebody smarter than me about why Rust chooses what it does, what else you could choose and what the price is: https://without.boats/blog/why-async-rust/ https://without.boats/blog/why-async-rust/ tl;dr: You can have different (nicer to program) abstractions, but you can't have them in the same language you use to write firmware for a $10 electronic device, or Linux drivers, and we already have languages like Go and Javascript whereas we did not have a safer alternative to C++.
- cchance 3y agoIt feels like most of the hatred for rust async is for people that try to act like Tokio isn't async rust and that for some reason you should try to randomly avoid tokio for some reason.
- speed_spread 3y agoMaybe because you want to keep the dependency tree under control and bringing in tokio suddenly adds fifty crates you never asked for. Every crate is a potential liability!
- pornel 3y agoTokio is developed very carefully (they’ve even developed their own thread race checker for it – loom). Adding it to your project probably increases the average code quality:)
- speed_spread 3y agoI don't doubt the code quality but most of the additional crates are not tokio's. Also statistically, any added complexity incurs more risk.