4 ms·
I think std needs a default runtime, and we might as well make it tokio, but maybe make the single-threaded executor the default instead and tweak the API where
by lucasyvas 3y ago
I think std needs a default runtime, and we might as well make it tokio, but maybe make the single-threaded executor the default instead and tweak the API where appropriate to align with this change.
Swapping the executors out should absolutely be a feature, and the traits should be portable, but a way to start fixing the situation beyond the great suggestions in this proposal is to acknowledge that std and no-std users are different, and std users are often developing applications and prefer sane defaults.
- steveklabnik 3y ago> I think std needs a default runtime, and we might as well make it tokio Regardless of the quality of this idea, it isn't going to happen: neither the Rust Project nor Tokio (in my understanding, to be clear I am not involved in either) want this to happen. > Swapping the executors out should absolutely be a feature, and the traits should be portable I am not fully aware of all of the details here but there are significant problems when it comes to actually getting this done; I don't think anyone is ideologically opposed, but there's a lot of practical considerations that make this difficult, in my understanding.
- alilleybrinker 3y agoTo pick out one example of what makes it challenging: not all executors place the same type system constraints on tasks they execute. Tokio, for example, is a work-stealing executor which requires tasks to implement the `Send` trait so they can be sent between threads, while other executors may never move tasks between threads and therefore don't require the `Send` bound.
- lucasyvas 3y agoYes, this is a major difference. But at this point, let's be honest - why has most stuff converged on Tokio? IMO it's not for reasons wholly of merit - it additionally won a popularity contest as one of the first movers. Why the popularity contest? Because people want an async executor, but they just want it to work. These people largely don't care about the benefits between different executors. I think they'd like the choice to use a different one, but they'd rather just having something available with async traits that trend toward opinionated. The executor issue is a huge problem, because the ideology of "zero opinion" on executor coupled with "ease of adoption" are completely at odds. I don't think the current trajectory will ever resolve nicely.
- mplanchard 3y agoWe experimented with both tokio and async-std and picked tokio on the merits. This was ~2 years ago, so things may have changed a bit, but tokio provided a lot more out-of-the-box, and we also wanted a multi-threaded executor so its defaults worked well for us.
- cmrdporcupine 3y agoI actually think we have a cultural problem due to the fact that many of the people coming into Rust recently are coming from a "full-stack" webdev background, where "frameworks" are huge, and feels like nobody worries about being coupled to one framework or another, just picking the right one. Which is in large part due to the history of JavaScript and so on. This is an influx of people who sense that tokio is the "right" way to do things -- tutorials, blog posts, example applications, and 3rd party libs all start with tokio... and they're not philosophically against being tied to it. Whereas my own sense of the Rust philosophy is supposed to be one of zero-cost abstractions (when possible), and for the language to provide nuts and bolts that I can assemble myself. My interest is in systems eng. I don't want to be tied specifically into the systems-eng choices that Tokio happens to have already made, even if they might be good ones. I want the ability to choose. It's not healthy, in my opinion, for one entity to dominate choices like this. If this can't be resolved, my sense is that people who have the same impulses as me will choose to either not use async at all, or move on from Rust.
- lucasyvas 3y agoI agree with you 100%, but members of the Rust project have stated in the past that async, in not insignificant ways, is a play to deliberately target the higher level web/service based crowd. So, the cultural issue is partially self-inflicted. I'm not even sure what I want in Rust. All I know is that people have a legitimate gripe being sold on Rust async for high level work, having it ergonomically fall much flatter than it should. It's very hard to satisfy everyone, which they are learning day by day. I do wish for the async story to mature a bit more so the implementors have a chance to show the community how good it can be. But the project needs to consider its messaging to the users it has courted over.
- tuetuopay 3y agoI would not think it would be that good. Having multiple runtimes is great for specific use cases. I would also fear that having "one standard endorsed runtime" would lead to either the death of the alternative ones, or to the freeze of it once it's in the stdlib and fall to oblivion (like many packages in the python standard library). What the stdlib actually needs is the proper set of traits/facades/whatever to interact with the current runtime. Just like they did with the Future trait. And add the handful of traits that go with them that tokio, futures, smol, etc have: AsyncRead, AsyncWrite, Stream, Sink, et al
- mplanchard 3y agoAgree on both points. While I don't find async rust hard to use as a library consumer, trying to write a runtime-agnostic library is (IMO) more difficult than it needs to be. I would like to see most of `futures` either be incorporated into the stdlib or used more consistently throughout the various runtimes.
- cmrdporcupine 3y agoI think we'd need, at least, runtime agnostic locks, channels, and a 'spawn' function (trickier). And ideally some I/O primitives somehow not tied to the runtime?
- cmrdporcupine 3y agoIn reality there aren't multiple runtimes in a real, pluggable, generic sense. There's tokio and then some niche things that are hard to build on top of because they're not tokio (despite being possibly technically superior in some way). Every async-focused dependency that is relevant effectively mandates Tokio. And I've been ridiculed in public and private forums for suggesting that there should be a way to write libraries generically so that they don't have a runtime dependency. (Right now, services as basic as locking and task spawning are coupled to tokio, at least, and people use them all over.). Major new things are being made, all coupled to tokio. And I think this is a shitty situation for a whole bunch of reasons. And others (looks like you, too) agree, but it feels like there's just no way this is going to get fixed. Like, this article here, it doesn't even mention this as a concern? In the context of a big picture discussion of async over the next 4 years. So I don't foresee any progress on this front, and it makes me want to just rip async out of my code entirely.
- bryanlarsen 3y agoI believe that without.boats (or somebody of similar prominence) proposed that pollster (https://docs.rs/pollster/latest/pollster/ https://docs.rs/pollster/latest/pollster/) or a similar async executor be pulled into std. I think it's a great idea. By blessing something that's not tokio you give a good incentive for library authors to test against more than one executor. And by being so far from fully featured pollster is never going to "win" so blessing it doesn't appoint a winner. And it gives an obvious solution for what people who don't want to use async in their code but do want to pull in an async library should do. edit: it was without.boats in this post: https://without.boats/blog/why-async-rust/ https://without.boats/blog/why-async-rust/
- Matthias247 3y agoIt was orginally me (https://github.com/rust-lang/rust/pull/65875 https://github.com/rust-lang/rust/pull/65875)