- cross-posted to:
- [email protected]
- [email protected]
- cross-posted to:
- [email protected]
- [email protected]
I think the best part about smol is its composability.
Unlike tokio which consists of one large integrated library, smol provides many smaller, mostly runtime-agnostic crates e. g. blocking to run blocking I/O on a thread pool or async-lock for async lock primitives.
Tokio handles that through feature flags.
A good topic to chat about.
But before that, I should mention that I had to use the browser’s inspector to disable that background color. Light and dark backgrounds are both fine (I have color inversion bindkeyed after all). It’s the ones in the middle like this one that are a no-no.
And while you could exclusively use the runtime and ignore the rest, it is easier and more common to buy into the entire ecosystem.
Stats? User surveys?
I would expect that many users (including myself) actually just use the runtime, directly or indirectly (e.g. via
async-global-executor
with thetokio
feature), while API usage is covered by crates likeasync-io
,async-fs
,async-channel
,blocking
, …etc.In fact, I would hypothesize that, from an ecosystem adoption POV,
tokio
’s only killer feature ishyper
’s dependence on it. If it wasn’t for that dependence,tokio
’s adoption, I would expect, would be much lower. But this is admittedly anecdotal.Any time we reach for an Arc or a Mutex it’s good idea to stop for a moment and think about the future implications of that decision.
This and the quote above it seem to be Rust intellectuals’ flavor of the month position.
It kind of reminds me of the lowering dependencies’ compile times craze from a few years ago. Stretching the anti-MT-RT narrative to the point of making bad advice like recommending sync channels for an IO task adds to the parallels.
The choice to use Arc or Mutex might be indicative of a design that hasn’t fully embraced the ownership and borrowing principles that Rust emphasizes.
Or maybe you know, using APIs that already existed in std for a reason, as intended!
It’s worth reconsidering if the shared state is genuinely necessary or if there’s an alternative design that could minimize or eliminate the need for shared mutable state.
Generally true. But probably false here.
People reaching for
Arc
+Mutex
/RwLock
/… (doesn’t have to be aMutex
) in asyc code are probably aware of alternative designs, but still decide to useArc
+Mutex
/RwLock
/… when it’s either necessary, or when it actually makes things simpler, and the downsides (performance) are of no measurable relevance, or the alternative design is actually slower (i.e. the multi-threaded runtime is actually helping).I would consider arguments that talk about “killing all the joy of actually writing Rust” in this context as either intellectual posturing, or simply disingenuous.
Otherwise, there is not much to disagree with.
As someone who has tried doing multithreaded design with Arc/Mutex, this is a complete nightmare. You constantly get into deadlocks and performance is abysmal, because Mutex is serializing access (so it’s not really async or multithreaded any more).
As someone who has tried doing multithreaded design with Arc/Mutex, this is a complete nightmare.
I myself often use channels. And pass owned data around.
I don’t think anyone argues that Arc+interior-mutation is ideal. But it’s the over-the-top language like “complete nightmare” that some may take issue with.
Note that I again make the distinction between
Mutex
, and all interior mutation primitives. BecauseMutex
is indeed a bad choice in many cases. and over-usage of it may indeed be a signal that we have a developer who’s not comfortable with Rust’s ownership/borrowing semantics.You constantly get into deadlocks and performance is abysmal, because Mutex is serializing access (so it’s not really async or multithreaded any more).
- Same note about
Mutex
specifically as above. - Avoiding deadlocks can definitely be a challenge, true. But I wouldn’t say it’s often an insurmountable one.
- What crate did you use for interior mutability,
async-lock
,tokio
,parking_lot
, or juststd
?
I used parking_lot back then.
- Same note about
In fact, I would hypothesize that, from an ecosystem adoption POV,
tokio
’s only killer feature ishyper
’s dependence on it.AFAICT, the current hyper v1 release candidate only depends on tokio for
tokio::sync::{mpsc, oneshot}
(andsync
is the only enabled feature).It’s intended to be runtime-agnostic. See also https://docs.rs/hyper/1.0.0-rc.4/hyper/rt/trait.Executor.html . I agree that its ecosystem is still very tokio-centric.
FYI, I had some time to check out
hyper
v1 today.The new API of
hyper
proper is very low-level. Directly usable API is apparently moved to ahyper-util
crate, which, as expected, does have a hard dependency on the tokio runtime.So, while it’s good that
hyper
proper won’t hard-depend on tokio rt, it appears that non-tokio-rt usage will either depend on a higher-level 3d party crate, or a lot of effort from directhyper
dependants to write a lot of glue code themselves.