Live data from Hacker News

Async Rust never left the MVP state

tweedegolf.nl

251–260 of 273 posts

Re: Async Rust never left the MVP state

#251
post #167

Earlier quoted context omitted.

> Regular code was already async. When you need to wait for an async operation, the thread sleeps until ready and the kernel abstracts it away Not really. I’ve observed async code often is written in such a way that it doesn’t maximize how much concurrency can be expressed (eg instead of writing “here’s N I/O operations to do them all concurrently” it’s “for operation X, await process(x)”). However, in a threaded wor…

> work stealing executors have long been known to offer significantly lower latency with more consistent P99 than traditional threads. This has been known since forever - in the early 00s Well, we know how to make "traditional threads" fast, with lower latency and more consistent P99 since forever^2, in the early 90s. [1] Sure, we can't convince that Finnish guy this is worthwhile to include in THE kernel, despite si…

Stackful coroutines give up a fair amount of efficiency in a number of places to make that workable. It’s fine if you want to use a lot more RAM and Go and Java make that tradeoff, but that’s not suitable for something like Rust. That’s why Rust and C++’s async implementation is rather similar in many ways. Stackful coroutines also play havoc with FFI which carries a huge FFI cost penalty across the board even for code that doesn’t care about coroutines. These aren’t theoretical tradeoffs to just hand wave away as “doesn’t matter” - it literally does for how Rust is positioned. No one is stopping you from using Go or the JVM if that’s the ecosystem you like better.

> lol, it is very hard to model anything proactor like io_uring with async Rust due to its defects.

Not really. People latched on to async cancellation issues as intractable due to one paper but I’m not convinced it’s unsolvable whether due to runtimes that consider the issue more fundamentally or the language adding async drop which lets the existing runtimes solve the problem wholesale.

The point I’m making is that I/O and hardware is fundamentally non-blocking and we will always pay a huge abstraction penalty to try to pretend we have a synchronous programming model.

Re: Async Rust never left the MVP state

#252

Earlier quoted context omitted.

I’m curious - why were you wrong? It still seems like a wart to me, all these years later. What am I missing?

I was a proponent of the postfix macro solution. `.await!` or `.await!()`, essentially. The idea was that this could be generalized, it was closer to existing syntax, etc. I was worried about features that I still don't love like `.match` etc (I'm more open to these now). Post-fix macros would have been very complex. Scoping alone is complex. `.await` kinda just works. It does everything you want and the one cost is…

The postfix macro does sound like a better solution tbh. Did you write the static assertions crate? If so, thank you. I’m a daily user.

Re: Async Rust never left the MVP state

#253
post #2

Great article! Love these types of deep dives into optimizations. Hope the project goal works out! I've felt before that compilers often don't put much effort into optimizing the "trivial" cases. Overly dramatic title for the content, though. I would have clicked "Async Rust Optimizations the Compiler Still Misses" too you know

So on the title, I picked this because it's simply the truth. Since async landed in 2019 or so, not much has changed. Yes, we can have async in traits and closures now. But those are updates to the typesystem, not to the async machinery itself. Wakers are a little bit easier to work with, but that's an update to std/core. As I understand it, the people who landed async Rust were quite burnt out and got less active an…

> So on the title, I picked this because it's simply the truth. Since async landed in 2019 or so, not much has changed.

Hi. The article calls Rust async an MVP. You should expect strong reactions when you frame it like that.

"MVP" has a generally understood meaning; distorting that is unhelpful and confusing. Rust's async was not an MVP when it was released in 2019. It was the result of a lot of earlier work.

Rust async: (a) works well for a lot of people and orgs in production settings and (b) is arguably better designed than most (all?) other async implementations. Calling it an MVP is far from "simply the truth". It is an opinion -- and frankly a pretty clickbaity one. I appreciate your article's attention to detail, but the title is straight up shameful sensationalism.

I strive to not reflexively defend the status quo, but I get really chafed when people conveniently blur the difference between fact and opinion.

Please argue on narrowest correct claims available. The current title overstates your claims and undermines its overall credibility. Your central claim (as I read it) is that for embedded software there are opportunities for async improvement in Rust. Yeah this might sound boring, but I think it's accurate.

My other main criticism of your article is when it claims Rust async breaks the "zero cost abstraction" principle. I don't buy this claim, because you do not show that hand rolling the code provides the same guarantees. A lot of people misunderstand what "zero cost" means; your article wouldn't be the first to give the wrong impression.

Writing is hard (different audiences bring different backgrounds), and I commend anyone who puts their ideas out into the world. Please take this as constructive feedback: please agree or disagree with me on the merits. Ask and engage where I'm unclear.

Re: Async Rust never left the MVP state

#254

Earlier quoted context omitted.

I was a proponent of the postfix macro solution. `.await!` or `.await!()`, essentially. The idea was that this could be generalized, it was closer to existing syntax, etc. I was worried about features that I still don't love like `.match` etc (I'm more open to these now). Post-fix macros would have been very complex. Scoping alone is complex. `.await` kinda just works. It does everything you want and the one cost is…

The postfix macro does sound like a better solution tbh. Did you write the static assertions crate? If so, thank you. I’m a daily user.

Ha, no, I did not write that crate. I think my use of this username probably predates rust, certainly that crate.

Postfix macros had some very tricky issues and it would have delayed things a lot to figure out the right resolution.

Re: Async Rust never left the MVP state

#255

Earlier quoted context omitted.

Wait which programming model are you arguing is the low latency one? I thought you said it was JS because non-blocking.

Event loops are also non blocking. That’s literally why JS is non blocking. But event loops and callbacks are extremely hard to scale and maintain and keep non blocking. That’s why async/await is a more powerful abstraction - you don’t pretend I/O is this blocking thing, you interleave other work while it’s being done, and you don’t get impossible to follow callback hell. VS6 suffered from non responsive hangs all th…

Also, the parts they couldn’t make non-blocking (eg file reads) were precisely where VS6 would shit the bed and hang the entire UI trying to open a large file.

Re: Async Rust never left the MVP state

#256

Earlier quoted context omitted.

When you block the OS does the same thing - yields to other threads.

Yes, and it is extremely expensive. This is a well-known design problem in database engines. The computational cost of context-switching threads at yield points is often many times higher than the actual workload executed between yield points. To address this you either need fewer yield points, which reduces concurrency, or you need to greatly reduce the cost of yielding. An async architecture reduces the cost of yie…

> The computational cost of context-switching threads at yield points is often many times higher than the actual workload executed between yield points.

I would they this often is 1% of cases. As for Rust ecosystem, it doesn't make much case to add so much complexity and inconvenient abstractions to cover 1% of use-cases.

Re: Async Rust never left the MVP state

#257
post #64

I recently started working with Rust async. The main issue I am currently facing is code duplication: I have to duplicate every function that I want to support both asynchronous and blocking APIs. This could be great to have a `maybe-async`. I took a look at the available crates to work around this (maybe-async, bisync), but they all have issues or hard limitations.

There is work happening on keyword generics[0], which would let a function be generic over keywords like `async` and `const`. For now the best option to write code that wants to live in both worlds is sans-io. Thomas Eizinger at Fireguard has written a good article about this[1] pattern. Not only does it nicely solve the sync/async issue, but it also makes testing easier and opens the door to techniques like DST[2] I…

> For now the best option to write code that wants to live in both worlds is sans-io

Thanks for sharing! Reading the articles, it looks at me, it is a kind of manual reimplementation of the state machine generated by async? This also makes the code harder to reason with. I am unsure if it is worth the complexity.

Re: Async Rust never left the MVP state

#258

Earlier quoted context omitted.

I'll give my two cents here. I work with Dart daily, and it also uses the `await future` syntax. I can cite a number of ergonomic issues: ```dart (await taskA()).doSomething() (await taskB()) + 1 (await taskC()) as int ``` vs. ```rust taskA().await.doSomething() taskB().await + 1 taskC().await as i32 ``` It gets worse if you try to compose: ```dart (await taskA( (await taskB( (await taskC()) as int )) + 1) ).doSometh…

Two spaces before a line make it a code block literal This is a code block HN has never used markdown so the triple-tick does nothing but create noise here.

Thnaks for heads up, I'll keep this in mind in the future.

Re: Async Rust never left the MVP state

#259

Earlier quoted context omitted.

I believe that's actually how the virtual threads in the newer Java works. It's smart enough to notice IO and properly park it and move to another thread. I think it's still basically doing epoll behind the scenes [1], but you have straightforward sequential code in the process and the actual implementation is invisible to the user, and you can use old boring blocking code with an object that is a drop-in replacement…

> but I'm definitely an outlier for that You are not. I prefer the same and that's how my product works right now. My HTTP API is Vert.x-only with futures. My particular use case is thousands of devices sending small packages to the API in undefined periods of time or in bursts, so I find Vert.x event-loop performance quite a good match for my use case. In fact it has been very positive given customer feedback thusfa…

Glad I'm not alone! I find having the actual asynchrony itself as an object I can play with to allow for for some nice fine-grained concurrency and allows me to be very explicit about when blocking happens.

It makes sense that they would use epoll under the covers; I would have been surprised if they weren't using epoll or io_uring/kqueue.

Re: Async Rust never left the MVP state

#260
post #253

Earlier quoted context omitted.

So on the title, I picked this because it's simply the truth. Since async landed in 2019 or so, not much has changed. Yes, we can have async in traits and closures now. But those are updates to the typesystem, not to the async machinery itself. Wakers are a little bit easier to work with, but that's an update to std/core. As I understand it, the people who landed async Rust were quite burnt out and got less active an…

> So on the title, I picked this because it's simply the truth. Since async landed in 2019 or so, not much has changed. Hi. The article calls Rust async an MVP. You should expect strong reactions when you frame it like that. "MVP" has a generally understood meaning; distorting that is unhelpful and confusing. Rust's async was not an MVP when it was released in 2019. It was the result of a lot of earlier work. Rust as…

> Rust's async was not an MVP when it was released in 2019

The team literally described it as such.

One of the main architects of Rust’s async/await, withoutboats, left a comment on lobsters:

> It's just the truth. Neither in the language design nor in the compiler implementation has hardly any progress been made in the now 7 years since we shipped the MVP. The people primarily involved in delivering the MVP all become less active in the project around the same time and delivery since then has stalled out.

>

> I hope this person receives the support to do this work.

Rust’s async is great, and I feel you around some of the less informed criticisms. But it’s been called an MVP for a decade now, it’s not an insulting characterization. Just because it’s been an MVP does not mean it’s not good or useful.

Post reply on HN