Live data from Hacker News

Portable and Interoperable Async Rust

ncameron.org

21–30 of 71 posts

Re: Portable and Interoperable Async Rust

#21

Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime? Maybe it just wasn’t a focal area for the original Rust designers?

>Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime?

Rust made the deliberate decision to avoid the heavier Go goroutines runtime model after early alpha/beta experiments showed it conflicted with Rust's low-level design. I found 3 links to some history of that rationale in a previous comment:

https://news.ycombinator.com/item?id=28660089

And some more links:

https://stackoverflow.com/questions/29428318/why-did-rust-re...

https://github.com/rust-lang/rfcs/blob/master/text/0230-remo...

And lots of debate in this previous thread: https://news.ycombinator.com/item?id=10225903

Re: Portable and Interoperable Async Rust

#22
post #8

On a somewhat unrelated note: What consequences did the Rust mod team resignation lead to? The last thing I heard was the blog post: https://blog.rust-lang.org/inside-rust/2021/11/25/in-respons... But I haven't seen any public discussions on the future of Rust governance, how to make the core team accountable, or other consequences since.

The rust core team is/was never accountable. Which is fine because the language work is done elsewhere thankfully.

Re: Portable and Interoperable Async Rust

#23

Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime? Maybe it just wasn’t a focal area for the original Rust designers?

It's extremely challenging to make async that is usable without introducing a garbage collector or a whole lot of runtime overhead. A better comparison would be between the Rust and C++ paths to async - C++ also spent years designing their async system, and the end result is divisive at best.

True, and as the sibling comment notes it is still not fully there, yet as the vocabulary types are part of the standard library, it means what I have coded running on top of C++/WinRT, might equally work on top of HPX or cppcoro, just by changing includes and library being linked.

Re: Portable and Interoperable Async Rust

#24
post #5
post #4

Earlier quoted context omitted.

Go is a very different language than rust. Go has automatic memory management & garbage collection. This automatically disqualifies it from being used in many scenarios that rust is designed to support, like embedded systems. Go’s runtime model just makes stuff like this vastly simpler. Rust can’t impose the same kind of runtime model that go has.

While Go isn't designed for embedded systems, it can run on them. TinyGo is another Go compiler intended for embedded systems. And now its officially sponsored by Google. https://tinygo.org/docs/reference/microcontrollers/

TamaGo is another example, https://www.f-secure.com/en/consulting/foundry/usb-armory

Re: Portable and Interoperable Async Rust

#25
post #10

Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime? Maybe it just wasn’t a focal area for the original Rust designers?

The saddest part of learning Rust was discovering that there are no goroutines and that async works like Python and everything needs to be written twice to support both async and blocking styles. Like it was 20 years ago all over again and I'm still trying to mix Twisted and stdlib Python. I got all excited thinking of how the borrow checker would work so well with coroutines, only to discover it got nobbled because…

I find traditional multi threading a pleasure in Rust, and it works really well with the borrow checker and how the type system is designed (like the Send and Sync traits).

On the semantic side, extending it to a N:M threading model like Erlang or Go would work great. But that model only seems to work well if you basically make the entire language async, which is in conflict with too many of rust's goals. So we are left with the somewhat awkward state of async as a second class citizen.

Re: Portable and Interoperable Async Rust

#26
Rust is a mess. This effort will just result in yet-another "zero cost abstraction" where the real cost is developer time and sanity.

Rust governance seems to have become Lord Of The Flies...and I don't think the author of this piece is holding the Conch. At least C++ has a standard that everyone accepts even if they disagree with it.

Unfortunately the Rust hype machine is so overwhelming that many orgs will be forced to waste months trying to adopt it just to satisfy one alpha dev who "fell for it" and suddenly believes system memory is more expensive than developer time.

It is serious and risky work saying "no" to devs who want to rewrite everything in Rust, but you have to be brave

Rust is not the future. The future will indeed be garbage-collected, and the true innovation will be to optimize GC runtimes to make them useful in more and more scenarios.

Re: Portable and Interoperable Async Rust

#27
post #14

Earlier quoted context omitted.

It's extremely challenging to make async that is usable without introducing a garbage collector or a whole lot of runtime overhead. A better comparison would be between the Rust and C++ paths to async - C++ also spent years designing their async system, and the end result is divisive at best.

And we are not even done yet. The Networking TS seems to have fallen out of favor and now it seems we are going to get executors + senders/receivers, which I personally think is pretty cool actually.

Wonder if the Rust team is aware of the work on the C++ side of the fence on the executors+senders/receivers approach: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p230...

Not saying that is the ultimate answer to building async and/or parallel algorithms, but being aware of what others in the same space are doing is certainly useful.

Re: Portable and Interoperable Async Rust

#28
post #10

Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime? Maybe it just wasn’t a focal area for the original Rust designers?

The saddest part of learning Rust was discovering that there are no goroutines and that async works like Python and everything needs to be written twice to support both async and blocking styles. Like it was 20 years ago all over again and I'm still trying to mix Twisted and stdlib Python. I got all excited thinking of how the borrow checker would work so well with coroutines, only to discover it got nobbled because…

I only have rudimentary knowledge of Golang (but think the blocked/green automatic scheduling is excellent).

How does go nest aync calls?

func f() { }

func g() { }

func h() { go g() go f() }

What happens on

f()

Are the g() and f() calls inside h() blocking? Or are they async and the block happens at the point of return? Which would be the main difference to languages with an async keyword, were you need to be explicit about blocking.

Re: Portable and Interoperable Async Rust

#29

Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime? Maybe it just wasn’t a focal area for the original Rust designers?

> Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime?

It’s not that Rust has struggled, it was never Rust’s priority to have a runtime or high level async code. It had very different goals to Go.

It’s like asking “why has C struggled to implement Promises like JavaScript”? The languages serve different purposes.

You’re right it wasn’t their initial focal point but later on Rust wanted to offer the chance of having a go-like runtime without destabilising the low-level performance at the core level. I.E only those that use it pay for it and those that don’t use it aren’t affected.

Offering “zero cost” futures etc is very difficult to do.

See https://aturon.github.io/blog/2016/08/11/futures/ for more info, old but still relevant (including the chart)

Re: Portable and Interoperable Async Rust

#30

Why has Rust struggled so much with this, where Go has succeeded from the start with its language-level “goroutine” concept and runtime? Maybe it just wasn’t a focal area for the original Rust designers?

I think part of it is because computer science hasn't really nailed the right abstraction for concurrent code execution.

For instance, C is a great abstraction. You take assembly language, abstract away manual management of registers with variables and pointers, add structured types to describe memory layout, standardize flow of control operations, and add functions to enable code reusability, and you have something which is very easy to work with and also to understand. It's not 100% on par with assembly in terms of performance, but it's pretty darned close, and with a little bit of practice it's very easy to look at a block of C code and basically understand what equivalent assembly it compiles to. It's a great abstraction, and it's no wonder that a vast majority of the languages which have come after it have borrowed most of its major features.

I would argue we haven't really had a "great abstraction" to the same level since then*. There have been efforts to abstract away memory management the way register management has been abstracted away, and many of them have been successful for a lot of use-cases, but not to the point that everyone can forget about memory management the way the vast majority of us can forget about register management. Garbage collectors can be too slow or too wasteful for a lot of use-cases, and you need essentially another program you didn't write to pull it off. In a GC'd language it's not so trivial to look at a block of high-level code and predict what your CPU will do. There are other approaches: like the structured approaches of Rust and Swift which are quite interesting, but they're far from proven at this point.

Similarly I think we're not quite there yet with concurrent programming. As far as the transparency topic, a lot of async implementations are more in the direction of garbage collectors, where the compiler rips apart your code and builds a state machine in its place. It's not hard to believe that the result will be difficult to work with and reason about in some cases.

And maybe the problem is that most approaches to async are trying to cram concurrent execution into that C-like abstraction, which is such an elegant abstraction for single-threaded execution exactly. Maybe concurrent programming needs to be re-thought from first principals, with different primitives involved.

*Aside: if there is another "great abstraction" on the horizon, I believe it to be ADT's. That is a feature of programming which feels like a clear step forward with no clear downsides. It's a shame that they haven't been included in Zig.

Post reply on HN