Live data from Hacker News

Why asynchronous Rust doesn't work

theta.eu.org

141–150 of 499 posts

Re: Why asynchronous Rust doesn't work

#141
post #56
post #30

I've been primarily coding in rust since 2018. I never cared for async/await, and I've never used it. (at some point, coding event loops became very natural/comfortable for me, and I have no trouble writing "manual" epoll code with mio/mio_httpc). one nice thing about rust's async/await is, you don't have to use it, and if you don't, you don't pay for it in any way. sure, I run into crates that expect me to bring in…

Maybe it’s just the hyper and related crates universe, but my perception (see my sibling comment) is that more and more of the ecosystem will be “async only”. Like you, I think that’s sort of fine, because you can always roll your own. But it’s also kind of sad: one of the best things about the Rust ecosystem is that you can so effortlessly use a small crate in a way you really can’t in C++ (historically, maybe modul…

I mean, you can always just use an async crate and use async_std::task::block_on.

Re: Why asynchronous Rust doesn't work

#142
post #88

Earlier quoted context omitted.

> maybe it was a mistake to adopt an async paradigm from functional languages > I think Rust was right to pick Scala-style async I'm confused by this assertion. I'm more aware of procedural language origins of syntactic async/await than functional? The scala proposal in 2016 for async/await even cites C#'s design (which came in C# 5.0 in 2012) as an inspiration[1]. From there, it appears python and typescript added t…

> I'm more aware of procedural language origins of syntactic async/await than functional? The scala proposal in 2016 for async/await even cites C#'s design (which came in C# 5.0 in 2012) as an inspiration[1]. The C# version comes from F# (2007) which was in turn inspired by the "Poor Man's Concurrency Monad" implementation for Haskell (1999) (in turn inspired by Concurrent Haskell and, ultimately, Concurrent ML). It'…

I wasn't aware of the F# heritage, that's interesting. I'm curious why the scala proposal wouldn't cite it. Especially surprising since scala's at least superficially looks more like F#'s than it does like C#'s.

I don't dispute (as I have had to say repeatedly in other branches of this) that the roots of futures as a concept are in functional programming, but the path I'm saying I see here is effectively:

    - haskell/monads
    |- do-notation
    |- monadic futures
    |- (this is new to me) F# appears to have added 'types' of do blocks, including a specifically async one?
    \-> async-await as a sort of re-integration of quasi-monadic evaluation into procedural languages like C#, python, and eventually javascript and rust.
So what's weird to me is drawing a direct line between scala and rust here when the relevant precedent seems to be procedural languages distilling a thing from functional languages into a less flexible syntactic-sugar mechanism we now usually call async-await. Scala seems like a footnote here, where if you want to claim its descent from functional languages you would go farther back.

Re: Why asynchronous Rust doesn't work

#143
post #100

Earlier quoted context omitted.

> The problem is that Rust async was rushed without careful deliberation As someone who observed the process, this couldn't be further from the truth. Just because one disagrees with the conclusion does not mean that the conclusion was made in haste or in ignorance. > Without introducing Rust 2? Highly unlikely. This is incorrect. async/await is a leaf node on the feature tree; it is supported by other language featu…

>Just because one disagrees with the conclusion does not mean that the conclusion was made in haste or in ignorance. Believe me, I do understand the motivation behind the decision to push async stabilization in the developed form (at least I think I do). And I do not intend to argue in a bad faith. My point is that in my opinion the Rust team has chosen to get the mid-term boost of Rust popularity at the expense of t…

> My point is that in my opinion the Rust team has chosen to get the mid-term boost of Rust popularity at the expense of the long-term Rust health.

I don't think a conscious decision of that sort was made? My impression is that at the time the road taken was understood to be the correct solution and not a compromise. Is that wrong?

Re: Why asynchronous Rust doesn't work

#144
post #100

Earlier quoted context omitted.

> The problem is that Rust async was rushed without careful deliberation As someone who observed the process, this couldn't be further from the truth. Just because one disagrees with the conclusion does not mean that the conclusion was made in haste or in ignorance. > Without introducing Rust 2? Highly unlikely. This is incorrect. async/await is a leaf node on the feature tree; it is supported by other language featu…

>Just because one disagrees with the conclusion does not mean that the conclusion was made in haste or in ignorance. Believe me, I do understand the motivation behind the decision to push async stabilization in the developed form (at least I think I do). And I do not intend to argue in a bad faith. My point is that in my opinion the Rust team has chosen to get the mid-term boost of Rust popularity at the expense of t…

Does anything about the implementation of async prevent a future completion-based async feature? Say it's called bsync/bwait.

Re: Why asynchronous Rust doesn't work

#145
post #26

I don't think any of this is actually a reason why async rust doesn't work. The function color problem is a bit overblown, it hasn't broken nodejs yet either. Most code is sync, sync can call async and vice versa, and the ecosystem hasn't come tumbling down yet (since most Rust isn't whichever async application runtime for web apps is currently in vogue - its a systems language after all). Either way there are bigger…

I agree on generatorasync conversion.

I'm not an expert but I can't shake the thought that Rust had it backward with async and generator. Generator looks like a good bridge between sync and async. Before reading about implementing async executor and digging under what tokio and async-std is doing (it's been months and I haven't finished), I thought implementing async executor is just as easy as running looping a generator.resume() until it yields GeneratorState::Complete until I realize generator is still on nightly!

It may be because I'm a noob in Rust, but I can't write easily:

``` let some_handle_arc = Arc::new(some_handle); future::block_on([ // this future will stop running midway if some_handle is modified in some way make_future(some_handle_arc),

  // make_future_stopper will modify some_handle_arc when receiving
  // a certain input from a certain interface
  make_future_stopper(some_handle_arc)
]); ```

My initial intuition is if async is generator-based, there should be an escape hatch where the generator-runner just exit, drop the generator, without waiting for the generator to yield Generator::Complete. But again it might be from my noobness being a simple Rust hobbyist.

Sorry for the rant

Re: Why asynchronous Rust doesn't work

#146
post #56

Earlier quoted context omitted.

Maybe it’s just the hyper and related crates universe, but my perception (see my sibling comment) is that more and more of the ecosystem will be “async only”. Like you, I think that’s sort of fine, because you can always roll your own. But it’s also kind of sad: one of the best things about the Rust ecosystem is that you can so effortlessly use a small crate in a way you really can’t in C++ (historically, maybe modul…

I mean, you can always just use an async crate and use async_std::task::block_on.

Only if no other crate in your executable uses tokio or another executor, right?

Mixing executors is approximately fatal, AFAICT.

Re: Why asynchronous Rust doesn't work

#147
post #129
post #30

I've been primarily coding in rust since 2018. I never cared for async/await, and I've never used it. (at some point, coding event loops became very natural/comfortable for me, and I have no trouble writing "manual" epoll code with mio/mio_httpc). one nice thing about rust's async/await is, you don't have to use it, and if you don't, you don't pay for it in any way. sure, I run into crates that expect me to bring in…

I don't know how anybody can say this with a straight face. Even in a systems context I think it's pretty reasonable to want to either perform or receive a HTTP request, as soon as you do that in Rust you are funneled into Hyper or something built on top of it (like reqwest) and instantly are dependent on tokio/mio. The very first example in the reqwest readme^1 has tokio attributes, async functions AND trait objects…

You can avoid async ecosystem with mio_httpc for http client. tiny_http for http server. Both work well.

Re: Why asynchronous Rust doesn't work

#148

Earlier quoted context omitted.

The pace it is going at, it’s not that far from it

I am curious where you get that impression. From what I could see, recent releases have just been "smoothing over pits" / filling in obvious type holes left over from older changes. Changes in rust edition 2021 are tiny and it seems to only exist in order to establish a regular cadence.

Disclaimer: I've only dabbled in Rust from time to time, but have not written anything serious with it.

Those kind of comments are not based on looking at Rust's features on a theoretical level.

It's more from the viewpoint of "How hard is it to get something (correctly) done". Those impressions are mostly formed either from using the language and failing (or having severe difficulties) to solve a given problem, or being exposed to blog posts describing those kinds of problems.

Rust sure does not have as many features as C++, but it seems that in practice, the combination of available features (and/or the problems those create) is perceived as just as complex as C++. Though not being a fair assessment, the Rust community will have to try fighting this perception, if Rust is not to be labeled way more complex than C++ in the coming years.

Re: Why asynchronous Rust doesn't work

#149
post #66

Earlier quoted context omitted.

Correct me if I'm wrong, but isnt any sort of async support non integral to rust? For example in something like Javscript you can't impliment your own async. But in C, C++ or Rust you can do pretty much anything you want. So if in the future io-uring and friends become the standard can't that just be a library you could then use? Similar to how in C you don't need the standard library to do threads or async.

I agree. Completion-based APIs are more high level, and not a good abstraction at the systems language level. IOCP and io_uring use poll-based interfaces internally. In io_uring's case, the interfaces are basically the same ones available in user space. In Windows case IOCP uses interfaces that are private, but some projects have figured out the details well enough to implement decent epoll and kqueue compatibility l…

> IOCP models tend to heavily rely on callbacks and closures

While perhaps higher level libraries are written that way, I can’t think of a reason why the primitive components of IOCP require callbacks and closures. The “poll for io-readiness and then issue non-blocking IO” and “issue async IO and then poll for completion” models can be implemented in a reactor pattern in a similar manner. It is just a question of whether the system call happens before or after the reactor loop.

EDIT: Reading some of the other comments and thinking a bit, one annoying thing about IOCP is the cancelation model. With polling IO readiness, it is really easy to cancel IO and close a socket: just unregister from epoll and close it. With IOCP, you will have to cancel the in-flight operation and wait for the completion notification to come in before you can close a socket (if I understand correctly).

Anyways, I've been playing around with implementing some async socket APIs on top of IOCP for Windows in Rust [1]. Getting the basic stuff working is relatively easy. Figuring our a cancellation model is going to be a bit difficult. And ultimately I think it would be cool if the threads polling the completion ports could directly execute the wakers in such a way that the future could be polled inline, but getting all the lifetimes right is making my head hurt.

[1] https://github.com/AustinWise/rust-windows-io

Re: Why asynchronous Rust doesn't work

#150
post #118
post #24

The author admits that they needed Arc/clone in a footnote. So I think the more interesting title would be to rehash/interpret this as “Why asynchronous Rust is too hard”. Having played with this a bit recently, I think folks are going to end up: - assuming Tokio (now that it’s 1.xx) - mark nearly everything as async - push callers to use rt.block_on to wait for an async function from non-async code I definitely miss…

I noticed this a few months ago as well. I was looking for a way to do simple synchronous HTTPS requests in a CLI, and it seemed like using `reqwest` with tokio was more or less the default option in Rust. I ended up using ureq, and it looked like there may have even been ways to avoid it using hyper and an alternative tls-connector but the simplest solution seemed to be "just use tokio". When something foundational,…

Yeah, I started with reqwest because it was easy, then wanted more control (reqwest has a hardcoded 8? KiB buffer!) and went to hyper directly, and then realized I should replace all reqwest usage with just async usage of hyper.

Doing so then colored/infected everything with async. It wasn’t actually bad in the end, but if you’re just trudging along trying to do your job, you suddenly walk into a “and now update all of this”. Staring at the innards of reqwest::blocking though made me realize “if I care about performance at all, I really shouldn’t use this”. One of my main reasons was so that I’d know there was only my inclusion of tokio/the version I wanted (reqwest lagged a bit, so then I had hyper w/ tokio1.0 and reqwest with an older hyper with an older tokio... and I was worried about understanding that interaction).

Post reply on HN