People crap on async Rust because it's not the most graceful to use, but I think it's kinda genius how they've managed to make it zero-overhead. To the point that even the stack size of green "threads" is known ahead of time.
The only issue I have is that it's tough not to use it. The big HTTP libraries let you opt out, but smaller libraries don't have the resources to do everything twice. I don't know what the solution is, but it would be nice to always be able to chose. It's pretty silly to use async networking in a cli app, for example, but sometimes you have to.
I disagree, because you're paying for boxing on return + dynamic dispatch when it's perfectly safe/sound to have a stackful coroutine that only allocates when the stack needs to grow and doesn't require dynamic dispatch. So you don't pay for heap allocated futures if they aren't necessary, and you pay less when they are.
So you're actually paying a higher price than if the compiler could support stackful generators for recursive futures. In fact async just gets a lot easier to write and use if generators could be stackful, at least imho. Generators don't have the syntax nice-ness of async/await, but they're also more explicit which feels more in with the rest of Rust, where syntax sugar like async/.await() is the exception and not the norm.
And as the sibling comment says, you can do that in your own code. It does still add Tokio to your binary size, and add some compile time, and probably start a bunch of worker threads you don't need, but it does work.
Yeah, one of the nice things about blocking I/O is that you can perform it with a single syscall. With block_on(async_io), you're now dealing with registration with a reactor, polling epoll, and extra syscalls for each I/O operation. Not to mention the overhead of running the state-machine as opposed to line by line.
Blocking I/O+threads can actually scale very well now, and with block_on you get the worst of both worlds, but yeah, I agree that most people are probably fine with it.
This assumes that people only use Rust for the performance. I don't think that's strictly true.
95% of what I write isn't performance-critical or even, really, performance-relevant. I still choose Rust for the vast majority of projects for ergonomic and correctness reasons.
You're spot on. I recently chose Rust over Python for a very small program which reads a JSON (or Hjson) file, does some checking and processing, and writes the results to a different JSON file, because Rust has serde, proper static type checking, algebraic data types, and other features that made it more productive than Python (!!!) for that specific use case. Performance wasn't even a consideration, I made judicious use of clone() and run it in debug mode.
Serde is such an awesome library. Having to decode serialized data in the other languages (Swift, C++, Python) I write is such a bear after using serde.
Swift comes closest with codable/decodable but it's often still lacking the ergonomics of serde, especially the attribute options per field
Some people who come to rest may not be fine with it.
A lot of people come to rust for other reasons, like compile time safety checks etc...
But most importantly, the delta between the performance of block_on and not, versus block_on and Python are massively different. You can write inefficient rust and still have a huge win over Python.
The only issue I have is that it's tough not to use it. The big HTTP libraries let you opt out, but smaller libraries don't have the resources to do everything twice. I don't know what the solution is, but it would be nice to always be able to chose. It's pretty silly to use async networking in a cli app, for example, but sometimes you have to.