Live data from Hacker News

How to think about async/await in Rust

cliffle.com

251–260 of 268 posts

Re: How to think about async/await in Rust

#251
post #124

Earlier quoted context omitted.

> Your comment seems to be conflating concurrency with parallelism. No, it really doesn't. I mention both concurrency and parallelism, and their main difference. > Threads are the opposite: They are interfaces for parallel programming No, they are not. Threads can do both. When waiting for an i/o bound operation, a thread can simply sleep. Added bonus: A thread basd implementation supports io bound concurrency and cp…

> 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 If the comment is not conflating concurrency and parallelism as you say, mind expanding on this part?

> mind expanding on this part?

Certainly. That part is a sentence written to be short and catchy. It sacrifices precision for reasons of brevity and style. It also doesnt mention either concurrency or parallelism, it just uses the word "parallel".

This is acceptable, because the post goes on to more precise statements later on, quote:

    It works for both i/o bound concurrency and cpu bound parallel computing.
End Quote.

Re: How to think about async/await in Rust

#252

Earlier quoted context omitted.

> Your comment seems to be conflating concurrency with parallelism. No, it really doesn't. I mention both concurrency and parallelism, and their main difference. > Threads are the opposite: They are interfaces for parallel programming No, they are not. Threads can do both. When waiting for an i/o bound operation, a thread can simply sleep. Added bonus: A thread basd implementation supports io bound concurrency and cp…

> When waiting for an i/o bound operation, a thread can simply sleep. I mean if you're fine with blocking I/O then obviously you don't need async, but on the other hand having non-blocking I/O is the whole point of async ^^

[deleted]

Re: How to think about async/await in Rust

#253

Earlier quoted context omitted.

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

There are use cases where a thread pool doesn't solve your problem. If you're handling a few short-lived connections at a time, it's more than enough, but if you're developing something like a push / messaging / queuing service, with thousands of clients connected for hours at a time and receiving very little data once every few minutes, a thread pool won't help you.

This is a solved problem.

I can run millions of goroutines on a laptop. These get mapped to a relatively small number (number of available CPU cores with default settings) by the runtime.

Re: How to think about async/await in Rust

#254
post #105

Earlier quoted context omitted.

Don't you need some kind of way of telling the compiler you would like barriers here? I think otherwise the helper thread could run on another cpu and the two cpus would operate on their own cached copies of foo. But then again I'm not 100% on how that works.

There are barriers for join. But without barriers, the risk is compiler reordering/lift to registers/thread scheduling. The CPU cache would not be the direct cause of any “stale” reads. https://news.ycombinator.com/item?id=36333034

Well I knew there were possible issues both from the compiler and the cpu. It seems you are right that the cache is kept coherent, however there is another issue owing to out-of-order execution of cpu instructions. Either way, gpderreta is probably right that thread.join tells the compiler to make sure it's all taken care of correctly.

Re: How to think about async/await in Rust

#255
post #111

Earlier quoted context omitted.

Futures in Rust are annotated with the #[must_use] attribute [1], same as the Result type [2]. This means the compiler will emit a warning (can be upgraded to an error) if you forget to await a future even if it doesn't return anything. [1]: https://doc.rust-lang.org/nightly/src/core/future/future.rs.... [2]: https://doc.rust-lang.org/nightly/src/core/result.rs.html#49...

You don't want the safety of your program to depend on whether the compiler emits a warning or not. And turning warnings into errors just encourages people to write 'let _ = ...' to get rid of the error.

Note that the lint for un-awaited Future doesn't mention the way to silence them by assigning to _:

  warning: unused implementer of `Future` that must be used
   --> src/main.rs:9:5
    |
  9 |     foo();
    |     ^^^^^
    |
    = note: futures do nothing unless you `.await` or poll them
    = note: `#[warn(unused_must_use)]` on by default

Re: How to think about async/await in Rust

#256

Earlier quoted context omitted.

> has been a popular technique in C and C++ for decades, with epoll(), kqueue, libevent/libev/libuv, Boost Asio, ASE, and so on. JavaScript is older than all of those. (Libuv in particular was harvested from Node, which was itself built on top of JavaScript.) Obviously JS didn't invent callback-based async IO, but I think you're forgetting how old JS is and how relatively new that style of IO is.

This thread is about async/await, which was added to JavaScript in 2017. Before then, async programming was only done with Node.js (unless you consider windows.setTimeout() to be "event-driven programming"), which came out in 2009. Event-driven programming was an established paradigm years before then.

> This thread is about async/await, which was added to JavaScript in 2017.

The article is about async/await, but the comments I'm replying to seem to be about asynchronous programming in general. JS was doing async for many years before async/await was added.

Re: How to think about async/await in Rust

#257

Earlier quoted context omitted.

This thread is about async/await, which was added to JavaScript in 2017. Before then, async programming was only done with Node.js (unless you consider windows.setTimeout() to be "event-driven programming"), which came out in 2009. Event-driven programming was an established paradigm years before then.

> This thread is about async/await, which was added to JavaScript in 2017. The article is about async/await, but the comments I'm replying to seem to be about asynchronous programming in general. JS was doing async for many years before async/await was added.

Nobody was doing async JS before Node, which came long after async I/O was an established paradigm.

Re: How to think about async/await in Rust

#258
I'm confused about this part:

    async fn my_state_machine() {
        set_pin_high();
        defer! { tristate_pin(); }

        sleep_for(Millis(100)).await;

        set_pin_low();
        sleep_for(Millis(100)).await;

        // Pin gets tristated here
    }
> This will ensure that a minimum of 100 ms elapses between our changes to the pin. We can’t impose a maximum using this approach, because – as we saw above – our caller could wait months between stepping our state machine, and that’s part of what we’re signing up for by writing this state machine.

Surely the example code _does_ ensure that both the minimum and the maximum wait times are approximately 100ms between changes to the pin? The functions set_pin_high() and set_pin_low() are just normal functions AIUI; they are not async (are not awaited). In the previous snippets the author used a pending!() macro, but that is not used here.

Re: How to think about async/await in Rust

#259

Earlier quoted context omitted.

> This thread is about async/await, which was added to JavaScript in 2017. The article is about async/await, but the comments I'm replying to seem to be about asynchronous programming in general. JS was doing async for many years before async/await was added.

Nobody was doing async JS before Node, which came long after async I/O was an established paradigm.

XMLHttpRequest shipped in 1999. AJAX was coined in 2005. The "A" in "AJAX" is for "asynchronous".

Re: How to think about async/await in Rust

#260

Earlier quoted context omitted.

> “everything is sequential” abstraction is leaky, Can you explain what details leak? The sequential model was developed for programming because that's a natural way to reason about proccesses. `if then else`. `do this, then do that. The "async/await" designers seem to agree, as they attempt to tame async by emulating this behavior. Note that to do anything other than sequential is extremely complicated to reason abo…

> Can you explain what details leak? You answer half of it a few lines later: > All sorts of concerns like: race conditions, synchronization, dead lock, etc are inherent. > Any approach that does not directly address these issues is the one that's creating a leaky abstraction. By writing `await` you're telling your reviewers, coworkers and even your future self than your program stops executing sequentially at this s…

> When using blocking code, the same thing can happen, but this is hidden from you.

I'm not convinced. I don't see how it is hidden from you. The blocking code works exactly as written. The mistaken assumption would be that your program will never be premempted or have to wait for resources.

> the magnitude difference

Rarely is a function call in C a single instruction. They are typically algorithms of non-constant complexity. So yes... but you're also picking the most extreme comparison. What about `fopen` vs `partial_sort`?

Post reply on HN