Live data from Hacker News

Asynchronous IO in Rust

medium.com

21–30 of 111 posts

Re: Asynchronous IO in Rust

#21

Earlier quoted context omitted.

Are you talking about threads-the-programming-model (vs. events, callbacks, channels, futures/promises, dependency graphs), or are you talking about threads-the-implementation-technique (vs. processes or various select()-like mechanisms)? And if you are talking about threads-the-programming-model, which synchronization mechanism: locks, monitors, channels/queues, transactional memory? If the various threads in your a…

Do you have any links on the "dependency-graph dataflow system" that you are talking about? Sounds a little bit similar to what I'm trying to do, except at higher scale.

I've seen an OCaml library, but I'm searching for solutions in other languages:

https://blogs.janestreet.com/introducing-incremental/

http://www.umut-acar.org/self-adjusting-computation

Re: Asynchronous IO in Rust

#22

Earlier quoted context omitted.

Are you talking about threads-the-programming-model (vs. events, callbacks, channels, futures/promises, dependency graphs), or are you talking about threads-the-implementation-technique (vs. processes or various select()-like mechanisms)? And if you are talking about threads-the-programming-model, which synchronization mechanism: locks, monitors, channels/queues, transactional memory? If the various threads in your a…

Do you have any links on the "dependency-graph dataflow system" that you are talking about? Sounds a little bit similar to what I'm trying to do, except at higher scale.

The specific systems I'm thinking of were Google-internal, but there's a close public analogue with Guice & Dagger:

https://github.com/google/guice

https://github.com/square/dagger

Imagine injecting Futures into your code. Now imagine injecting them, but having the Provider record a lot of metadata about who you were calling, how you were calling it, how long it took, whether an error occurred, letting an SRE turn off the call, etc.

Re: Asynchronous IO in Rust

#23
post #17

Earlier quoted context omitted.

Well, I believe that it's almost impossible to make rust threads lightweight because every green thread needs a stack anyway. This may be fixed with some stuff like `async/await`. But let's talk about what's wrong with threads: 1. Timeout handling is ugly: you need to account a timeout in each read and write operation. At least timeout handling makes coroutine/threaded code no better than state machine code. But actu…

I've been writing in this model for nearly ten years now. In practice, what you cite as problems aren't. 1: In either approach, somewhere in your event loop you're setting yourself a timeout to fire. Haskell & Erlang do use exceptions, but Go does not, it simply makes this a first-class concern of the core event loop. This is only a problem in languages where the threading was bolted on after-the-fact. Which is a lot…

"Communicating" doesn't solve deadlocks.

Thread 1 sends message A to thread 2 and waits for a response.

As part of processing message A, thread 2 sends message B to thread 1 and waits for a response... forever, since thread 1 is blocked waiting for thread 2...

Re: Asynchronous IO in Rust

#24
post #9
post #7

Earlier quoted context omitted.

There are some examples of speed difference at https://en.m.wikipedia.org/wiki/Green_threads Basically if you have green threads with only one core, you don't need to do as much work with locking.

The argument here is less about the performance difference existing or not, and that the decision in question sounds to have been made due to the lack of something we care less about.

I was responding to the first paragraph, which is technically all about the performance differences. (it does say "How could it be the case that virtual threads implemented in user space are faster than native threads provided by the OS?") Whether that matters and is a valid decision point is a completely different question as you say.

Re: Asynchronous IO in Rust

#25
post #23
post #17

Earlier quoted context omitted.

I've been writing in this model for nearly ten years now. In practice, what you cite as problems aren't. 1: In either approach, somewhere in your event loop you're setting yourself a timeout to fire. Haskell & Erlang do use exceptions, but Go does not, it simply makes this a first-class concern of the core event loop. This is only a problem in languages where the threading was bolted on after-the-fact. Which is a lot…

"Communicating" doesn't solve deadlocks. Thread 1 sends message A to thread 2 and waits for a response. As part of processing message A, thread 2 sends message B to thread 1 and waits for a response... forever, since thread 1 is blocked waiting for thread 2...

I don't understand that scenario — isn't message B the message thread 1 is waiting for?

And to be fair, it does significantly reduce the risk of deadlock by avoiding the complexity of explicit mutexes and condition variables.

Re: Asynchronous IO in Rust

#26
post #7

Earlier quoted context omitted.

> Green threads didn't provide performance benefits over native threads in Rust. That's why they were removed. This seems wrong. This shouldn't be the point of green threads -- green threads aren't a "faster" alternative to native threads. How would that work? How could it be the case that virtual threads implemented in user space are faster than native threads provided by the OS? I don't think anyone expects that to…

There are some examples of speed difference at https://en.m.wikipedia.org/wiki/Green_threads Basically if you have green threads with only one core, you don't need to do as much work with locking.

> Basically if you have green threads with only one core, you don't need to do as much work with locking.

This is half the basis for the original design of the Erlang BEAM VM. SMP was a grudging afterthought; the original concept was that each VM "node" was a single scheduler process bound to a single core, and then you tied those nodes together into a (machine-internal) multi-core distributed system, effectively creating a set of "threads" communicating over socket-based message-passing IPC, rather than shared memory.

M:N scheduling—where, critically, a task can be re-scheduled from one core to another—is a much more complex and less-predictable design, that's not always worth the trouble. For Erlang's particular use-cases, it turned out to be worth the trouble enough to justify programming it, eventually. But the SMP VM is still only built via a configure flag, rather than displacing the M:1 VM as "the" VM.

Re: Asynchronous IO in Rust

#27

Earlier quoted context omitted.

> Green threads didn't provide performance benefits over native threads in Rust. That's why they were removed. This seems wrong. This shouldn't be the point of green threads -- green threads aren't a "faster" alternative to native threads. How would that work? How could it be the case that virtual threads implemented in user space are faster than native threads provided by the OS? I don't think anyone expects that to…

Rust's green threading was... unusual. It attempted to abstract green and native threads into a single API, which lead to a lot of unnecessary overhead: https://github.com/rust-lang/rfcs/blob/0806be4f282144cfcd55b... Sadly, that proposal also removed concurrent IO from the standard library, and it hasn't been replaced.

It may not be replaced in the standard library, but mio exists and is what most people use for non-blocking stuff.

Re: Asynchronous IO in Rust

#28
post #23

Earlier quoted context omitted.

"Communicating" doesn't solve deadlocks. Thread 1 sends message A to thread 2 and waits for a response. As part of processing message A, thread 2 sends message B to thread 1 and waits for a response... forever, since thread 1 is blocked waiting for thread 2...

I don't understand that scenario — isn't message B the message thread 1 is waiting for? And to be fair, it does significantly reduce the risk of deadlock by avoiding the complexity of explicit mutexes and condition variables.

A simple example of this would be two threads with two channels to each-other. A is in channel A, B is in channel B. While blocked on channel A, thread 1 can't handle messages in channel B.

Certainly a bit more contrived then deadlock with locks, though (which you can easily do with even a single thread, even in Rust).

Re: Asynchronous IO in Rust

#29
post #3

If you use threads, green or otherwise, you don't have to "implement" special code for composing things together, you get the full set of tools for composing code together, which includes, in passing, state machines, among all the other things it includes. This basically implements an Inner Platform Effect of an internal data-based language for concurrency that the language interprets, which will A: forever be weaker…

You might want to take a look at: lthread & lthread cpp

https://github.com/halayli/lthread

https://github.com/halayli/lthread_cpp

Re: Asynchronous IO in Rust

#30
post #5
post #4

Earlier quoted context omitted.

> What's so wrong with Rust threads, excepting perhaps them being heavyweight? (Far better to solve that problem directly.) Nothing. If threads work fine, use them! That's what most Rust network apps do, and they work fine and run fast. A modern Linux kernel is very good at making 1:1 threading fast these days. > And having written network servers with pretty much every abstraction so much as mentioned in the article…

I'm down with all that. I'm really arguing in favor of threading here rather than any particular model of it. Plus, if you write threaded code, you can change the runtime out. Rust guarantees all the hard parts, anyhow. I wouldn't even be surprised once Rust settles down further it turns out there's some sort of hybrid solution that is better than either 1:1 or M:N on its own because it has superior insight into what…

> I'm down with all that. I'm really arguing in favor of threading here rather than any particular model of it.

Oh, from an ergonomic point of view I'm in total agreement that imperative-looking code is the best. I've never liked explicit node.js-like continuation passing style or what have you.

Post reply on HN