4 ms·
Anecdotal evidence, but many large rust async code bases perform significantly better if you are using a single threaded runtime vs. a multithreaded runtime. H
by rklaehn 3y ago
Anecdotal evidence, but many large rust async code bases perform significantly better if you are using a single threaded runtime vs. a multithreaded runtime.
Here is an issue for the quinn crate that implements QUIC: https://github.com/quinn-rs/quinn/issues/1433 https://github.com/quinn-rs/quinn/issues/1433
We have had very similar experiences when developing https://github.com/n0-computer/iroh https://github.com/n0-computer/iroh
And this is with quinn still carrying around the synchronization primitives to make everything Send.
Another piece of anecdotal evidence: the functional collection library https://github.com/bodil/im-rs https://github.com/bodil/im-rs comes in two flavours: one using Arc and one using Rc. The reason for this is that you get a significant performance increase by using Rc (where manipulating the refcount is just an integer inc/dec) vs Arc where manipulating the refcount needs to be an atomic op.
Last but not least - often making futures Send requires you to box your futures. Send and lifetimes just does not play well together. Do something like this:
trait Foo {
type OpFut<'a>: Future<Output = ()> + 'a;
fn op(&self) -> Self::OpFut<'_>
}
This is what eventually you would want something like async_trait to desugar to. Use the above in a Send context, and you get a completely undecipherable higher-ranked lifetime error. So you are back to boxing all futures.
- Nullabillity 3y ago> Last but not least - often making futures Send requires you to box your futures. Send and lifetimes just does not play well together. Do something like this: You should ~never need to box your futures to make them Send. You do sometimes need to box them to make them Unpin, but most of the time this is a tradeoff where it's possible to find a way to avoid moving them instead. It seems like these screeds (both the OP and this reply) come from the misunderstanding that "X is hard, Y sometimes comes up in the errors when trying to do X, therefore X would be easy if we got rid of Y". In reality, Y often just demonstrates intricacies of X that you weren't thinking about.
- rklaehn 3y agoLook at the extremely popular async_trait macro crate: https://crates.io/crates/async-trait https://crates.io/crates/async-trait . What it does under the hood is to box everything. See https://github.com/dtolnay/async-trait#explanation https://github.com/dtolnay/async-trait#explanation You would think that you should be able to desugar async traits to something that does not need to box. But this is not possible with stable rust. There is an effort to make this possible. See for example this discussion here: https://blog.rust-lang.org/inside-rust/2022/11/17/async-fn-in-trait-nightly.html#limitation-spawning-from-generics https://blog.rust-lang.org/inside-rust/2022/11/17/async-fn-i... Initially it was thought that Send bounds would not be needed, but community feedback strongly suggests that Send is indeed needed. https://blog.rust-lang.org/inside-rust/2023/05/03/stabilizing-async-fn-in-trait.html https://blog.rust-lang.org/inside-rust/2023/05/03/stabilizin... All this is a real problem, and not just a "you are holding it wrong" problem. Edit: here is the - still open - issue about higher-ranked lifetime errors: https://github.com/rust-lang/rust/issues/102211 https://github.com/rust-lang/rust/issues/102211
- Nullabillity 3y agoYes, it currently needs to box. But again, Sync is just a symptom of the real issues here (async fns have unpronouncable return types, opaque return types (impl trait) isn't supported in traits, and we don't have a good syntax for expressing constraints on opaque return types). Getting rid of Sync wouldn't fix any of those issues.
- rklaehn 3y agoYou don't get weird higher-ranked lifetime errors when you use non Sync futures with hand-rolled async traits. I am not saying that this is the reason to use local futures. But if you have decided that local futures are the way to go anyway, it's a nice benefit.
- duped 3y ago> Send and lifetimes just does not play well together. That's the point!