Live data from Hacker News

How to think about async/await in Rust

cliffle.com

81–90 of 268 posts

Re: How to think about async/await in Rust

#81
post #59

Earlier quoted context omitted.

My opinion is the opposite, to the point I would argue that anyone advocating for multithreading for reasons other than executing things in parallel on different cores is extremely dangerous and shouldn't be allowed anywhere near a serious codebase.

Are you talking about Rust (which I don't know)? In Python the async people don't care much about correctness.

It's language-agnostic. The language with the most advanced concurrency memory model is C++.

Re: How to think about async/await in Rust

#82

Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…

Async is, in many situations, better than traditional threads. Threads are a resource hog. They take a lot of system resources, and so you usually want to have as few of them as possible. This is a problem for applications that could, in theory, support thousands of concurrent connections, if not more. With a basic thread-based model, you need 1 thread per connection, and if you have long-lived connections with infre…

Isn't that problem generally easily solved with a thread pool ? (that's what nginx does I believe)

Re: How to think about async/await in Rust

#83
post #12

Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…

To me, async is just "cooperative multitasking" with a quick paintjob It is, and not only to you. It is a way to save a call stack until a runloop calls it back. But what I can’t agree with is parallels with OS. Coop MT is only problematic in OS MT. When it’s your code there’s no unknown bad actor, and having multiple cooperative (mostly waiting) processes without scheduling them on a thread pool is a useful concept…

Async is great for dealing with I/O but it forgets that the CPU is a resource too.

Re: How to think about async/await in Rust

#84

Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…

Coming from C and having used thread and being totally ignorant to javascript, this article really helped me grasp async in js by clearing away implicit misconceptions I held :

https://medium.com/young-coder/5-misconceptions-about-asynch...

And also that talk on the event loop : https://www.youtube.com/watch?v=cCOL7MC4Pl0

Re: How to think about async/await in Rust

#85

Not specific to rust, but I think asynchronous programming in general is a hype. It didn't start because it is so awesome, it started because JS can't do parallel any other way. That's the long and short of it. People wanted to use JS in the backend for some reason. The backend requires concurrency. JS cannot do concurrency. Enter the event loop. Then enter some syntactic sugar for the event loop. And since JS is pop…

It began in C# in 2012 - 5 years before JavaScript. And C# does threads. And made its way to JavaScript via Typescript (whose creator also created C#).

It began in 1970's with programming languages like Concurrent Pascal.

https://en.wikipedia.org/wiki/Concurrent_Pascal

Simula,

https://en.wikipedia.org/wiki/Simula

And plenty of other ones,

https://en.wikipedia.org/wiki/Coroutine#Implementations

Re: How to think about async/await in Rust

#86

Earlier quoted context omitted.

Rust pretty much alleviates these dangers. At least no memory safety bugs because of multithreading. Logic bugs are still possible, of course, but the channel API and the scoped thread API in the standard library do help with those.

That is not true at all, "fearless concurrency" gives no valuable guarantees at all and is widely seen as one of the worst concurrency models in literature.

I don't dispute that, but I thought you were having C++ with threads as the starting point, in which case Rust very much gives you valuable guarantees.

Re: How to think about async/await in Rust

#87
post #55

Earlier quoted context omitted.

async/await doesn't entirely remove the need for mutexes and locks. We still need them if we have multiple coroutines using a shared resource across multiple yield points.

> We still need them if we have multiple coroutines using a shared resource across multiple yield points. We still need them if we have multiple parallel tasks (coroutines spawned non-locally) using a shared resource across multiple yield points. As long as the accesses to the shared variable are separated in time, sharing is fine. This is correct code: let mut foo = 1; async { foo += 1 }.await; foo += 1; println!("{…

the equivalent threaded code wouldn't need a mutex either:

   int foo = 1;
   std::thread ([&] { foo+=1; }).join();
   foo+=1;
   std::cout 
(sorry for the C++, I don't speak much rust).

Re: How to think about async/await in Rust

#88

Earlier quoted context omitted.

Async is, in many situations, better than traditional threads. Threads are a resource hog. They take a lot of system resources, and so you usually want to have as few of them as possible. This is a problem for applications that could, in theory, support thousands of concurrent connections, if not more. With a basic thread-based model, you need 1 thread per connection, and if you have long-lived connections with infre…

> Threads are a resource hog. Not really on any decent operating system, but if they are too heavy, there's still fibers aka green-threads aka stack-switching (which at least on Windows are an operating system primitive - but can be implemented in user code on any system that gives you direct access to the CPU stack and registers). I doubt that the async-await state machine code transformation which 'slices' sequenti…

The async/await model gives you exactly one guarantee: because the yield continuation is second class, at most one stack frame can be suspended, so the the amount of space that needs to be reserved for a task is bounded and potentially can be computed statically. This can be important for very high performance/very high concurrency programs, so I think the upsides can be more than the downsides in something like rust, C++ [1], and possibly C#. I still do not understand why async was deemed appropriate, for example, in python.

As an aside, there is a lot of confusion in this thread between general async operations and async/await.

[1] but of course C++ screwed it up by requiring hard to remove allocations.

Re: How to think about async/await in Rust

#89

Earlier quoted context omitted.

> We still need them if we have multiple coroutines using a shared resource across multiple yield points. We still need them if we have multiple parallel tasks (coroutines spawned non-locally) using a shared resource across multiple yield points. As long as the accesses to the shared variable are separated in time, sharing is fine. This is correct code: let mut foo = 1; async { foo += 1 }.await; foo += 1; println!("{…

the equivalent threaded code wouldn't need a mutex either: int foo = 1; std::thread ([&] { foo+=1; }).join(); foo+=1; std::cout (sorry for the C++, I don't speak much rust).

Point taken. What about this pattern (pseudo code, obviously it would require e.g. adding some code for tracking how much data there is in the buffer or breaking the loop on EOF, but it illustrates the point):

   mut buffer: &[u8] = ...;
   loop {  
     select! {
       _ = stream.readable() => stream.read(&mut buffer),
       _ = stream.writable() => stream.write(&mut buffer),
     }
   }

Re: How to think about async/await in Rust

#90

Earlier quoted context omitted.

the equivalent threaded code wouldn't need a mutex either: int foo = 1; std::thread ([&] { foo+=1; }).join(); foo+=1; std::cout (sorry for the C++, I don't speak much rust).

Point taken. What about this pattern (pseudo code, obviously it would require e.g. adding some code for tracking how much data there is in the buffer or breaking the loop on EOF, but it illustrates the point): mut buffer: &[u8] = ...; loop { select! { _ = stream.readable() => stream.read(&mut buffer), _ = stream.writable() => stream.write(&mut buffer), } }

One you add enough tracking meta data to to know how much there is in the buffer, you literally have implemented an SPSC queue.
Post reply on HN