Green threads vs Async

Rust provides only OS threads, and supports async/await. Granted.

Why is the actual trend to build async libraries (tokio, actix, etc.) rather than to build libraries of green threads? Is it more performant than green threads?

An inconvenient I see with Async is that it is forces to rewrite all the standard library in an async way, so that we end up with 2 languages : SyncRust and AsyncRust.

This problem is explained in detail by Bob Nystrom

Go doesn't have this problem thanks to green threads.

Is there a technical impossibility to implement green threads as an extra library?

8 Likes

Yes, green threads completely changes how code is compiled. You may have heard that Rust does not have a runtime, and one of the things this implies is that Rust can't use green threads.

Green threads basically involves having the compiler insert yield points everywhere so it can pause execution of any thread at any time. Additionally it would require the compiler to embed a library similar to Tokio in all applications so it can execute its green threads efficiently.

16 Likes

There's nothing preventing someone from creating a "green-thread pool" as a crate to be used by application writers, AFAIK.

1 Like

The issue is running stuff on those green threads. The green thread library must be able to preempt (i.e. interrupt) the current green thread on an OS thread so it can be replaced by another green thread.

Tokio has an article that talks a bit about preemption, including how it works in Go: Reducing tail latencies with automatic cooperative task yielding.

4 Likes

Go doesn't have this problem, not because there's no AsyncGo but actually there's no SyncGo.

In Go, every IO calls are made asynchronous underneath. What it actually do is to hide the await keyword to make it looks more like synchronous code. Cons? We can't put future combinators like join and select on it. Instead in Go we put 2 additional goroutines and combine them with a channel, which is suboptimal.

Unlike Go, Rust can't drop the sync version of code as it defeats the original purpose of the language - to replace libraries written in C.

12 Likes

Many thanks for all your answers, I am very pleased to have a chat with you.

Am I wrong if I say that green threads could have been a compiler option, just like --debug or --release?

1 Like

I mean, I suppose you could in the same sense that you could make a compiler that compiles Java code with one switch and Go code with another. But it wouldn't be comparable to the difference between --debug and --release.

Green threads are not just an optimization. They change behaviour in quite important ways, and Rust would no longer be the same language if you introduced them.

4 Likes

So, are we doomed to clog our codes with async and await everywhere forever?

Never say never, but specifically for Rust that syntax with those semantics will always be supported.

If your project doesn't need async/await, it can use something like the blocking module in reqwest to wrap the async code, but if you need the advantages of async/await, then yes, you need to use async/await.

1 Like

Thought of the day: nonstandard libraries are not always interoperable: e.g. reqwest will not work with async-std, as it requires tokio. And what if you need some library built on top of async-std, and some other one built on top of tokio?

3 Likes

You might be interested in Niko's async interviews -- interoperability is one of the topics discussed.

1 Like

One of the talks that got me interested in checking out the Rust language is this which talks about the history of threading and async in Rust:

It also discusses green threads vs Rust.

Full transcript is available at the same link so read that if you cannot or don't want to listen to the presentation. :slight_smile:

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.