Live data from Hacker News

Async Rust never left the MVP state

tweedegolf.nl

71–80 of 273 posts

Re: Async Rust never left the MVP state

#71

Earlier quoted context omitted.

In that sentence I’m referring to the abstract idea of a thread of execution as a model of programming, not OS threads. A green thread implementation could do it too. But what you said about kernel implementation is true. But are we really saying that the primary motivation for async/await is performance? How many programmers would give that answer? How many programs are actually hitting that bottleneck? Doesn’t that…

> But are we really saying that the primary motivation for async/await is performance? The original motivation for not using OS threads was indeed performance. Async/await is mostly syntax sugar to fix some of the ergonomic problems of writing continuation-based code (Rust more or less skipped the intermediate "callback hell" with futures that Javascript/Python et al suffered through).

In some languages, yes, in others (js/python) async is just workaround about not having proper threading.

Re: Async Rust never left the MVP state

#72

Async seems like an underbaked idea across the board. 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. But We didn’t like structuring code into logical threads, so we added callback systems for events. Then realized callbacks are very hard to reason about and that sequential control is better. So threads was the right program…

> 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…

> threads are inherently and inescapably too heavy weight to express concurrency in an efficient way

Your premise is wrong. There are many counterexamples to this.

Re: Async Rust never left the MVP state

#73
post #3

Earlier quoted context omitted.

Agree on title. Too dramatic. The author seems to be obsessing about the overhead for trivial functions. He's bothered by overhead for states for "panicked" and "returned". That's not a big problem. Most useful async blocks are big enough that the overhead for the error cases disappears. He may have a point about lack of inlining. But what tends to limit capacity for large numbers of activities is the state space req…

> [...] That's not a big problem [...] Depends somewhat on your expectations, I suppose. Compared to Python, Java, sure, but Rust off course strives to offer "zero-cost" high level concepts. I think the critique is in the same realm of C++'s std::function. Convenience, sure, but far from zero-cost.

To the point it got replaced by std::function_ref() in C++26.

Re: Async Rust never left the MVP state

#74

Async seems like an underbaked idea across the board. 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. But We didn’t like structuring code into logical threads, so we added callback systems for events. Then realized callbacks are very hard to reason about and that sequential control is better. So threads was the right program…

Proper modern languages offer both, you can keep your threads and reach out to async only when it makes sense to do.

Now the languages that don't offer choice is another matter.

Re: Async Rust never left the MVP state

#75
post #73

Earlier quoted context omitted.

> [...] That's not a big problem [...] Depends somewhat on your expectations, I suppose. Compared to Python, Java, sure, but Rust off course strives to offer "zero-cost" high level concepts. I think the critique is in the same realm of C++'s std::function. Convenience, sure, but far from zero-cost.

To the point it got replaced by std::function_ref() in C++26.

Exactly. And I guess that is also the gist of the article: async Rust needs additional TLC.

Re: Async Rust never left the MVP state

#76
post #49

Earlier quoted context omitted.

Why do you think they don’t struggle with input latency? Because the non blocking nature built into the browser model is so powerful and you cannot get that with threads.

Are you sure that latency-sensitive parts are written in async JS instead of having a separate UI thread (pool)? I have no idea myself, but without knowing the details it's hard to argue. Note, that browsers themselves, are usually written in languages like C++ or Rust. They run JS, but aren't written in it

Yes they are, the UI layer is mostly JS, outside the rendering and layout engines.

Re: Async Rust never left the MVP state

#77
post #46

Earlier quoted context omitted.

Async in Rust and C++ is nothing like it is in Python or NodeJS. Choose your own runtime is a very different model than having a default one. Not to mention Tokio (most popular runtime for Rust) is multi-threaded by default. So you have to deal with multithreading bugs as well as normal async ones. That is not the case with most async languages. For example both Python and NodeJS use a single thread to execute async…

> Async in Rust and C++ is nothing like it is in Python or NodeJS. Choose your own runtime is a very different model than having a default one. Python still has pluggable eventloops - this is sort of mandatory to interact with weird things like GUI toolkits, and Python's standard event loop was standardised pretty late in the game. Early on there was even an ecosystem split between Twisted and competing event loops i…

It is an inherent limitation. Multithreading is not free after all. One of the big pros of async programming is the concurrency you get within a single thread. When you make the async runtime multithreaded by default (like Tokio) you don't get this advantage anymore.

Re: Async Rust never left the MVP state

#78

Async seems like an underbaked idea across the board. 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. But We didn’t like structuring code into logical threads, so we added callback systems for events. Then realized callbacks are very hard to reason about and that sequential control is better. So threads was the right program…

As I understand, "green threads" are also expensive, for example you either need to allocate a large stack for each "thread", or hook stack allocation to grow the stack dynamically (like Go does), and if you grow the stack, you might have to move it and cannot have pointers to stack objects.

>and if you grow the stack, you might have to move it

Most stacks are tiny and have bounded growth. Really large stacks usually happen with deep recursion, but it's not a very common pattern in non-functional languages (and functional languages have tail call optimization). OS threads allocate megabytes upfront to accommodate the worst case, which is not that common. And a tiny stack is very fast to copy. The larger the stack becomes, the less likely it is to grow further.

>cannot have pointers to stack objects

In Go, pointers that escape from a function force heap allocation, because it's unsafe to refer to the contents of a destroyed stack frame later on in principle. And if we only have pointers that never escape, it's relatively trivial to relocate such pointers during stack copying: just detect that a pointer is within the address range of the stack being relocated and recalculate it based on the new stack's base address.

Re: Async Rust never left the MVP state

#79

Earlier quoted context omitted.

As I understand, "green threads" are also expensive, for example you either need to allocate a large stack for each "thread", or hook stack allocation to grow the stack dynamically (like Go does), and if you grow the stack, you might have to move it and cannot have pointers to stack objects.

works fine in Go. Yes, you're not getting Rust performance (tho good part of it is their own compiler vs using all LLVM goodness) but performance is good enough and benefits for developers are great, having goroutines be so cheap means you don't even need to do anything explicitly async to get what you want

Rust chose a different design space for their async implementation though, so what works well for Go wouldn't work well for Rust. In particular, the Rust devs wanted zero-cost FFI that external code doesn't need to know about, which precludes Go-like green threads.

Re: Async Rust never left the MVP state

#80
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…

Some of the burnout no doubt being due to the catastrophizing of every decision by the community and the extreme rhetoric used across the board.

Great to see people wanting to get involved with the project, though. That’s the beauty of open source: if it aggravates you, you can fix it.

Post reply on HN