Live data from Hacker News

Async-await on stable Rust

blog.rust-lang.org

51–60 of 392 posts

Re: Async-await on stable Rust

#51
post #30

Isn't it kind of a poor design choice that Rust will not actually begin execution of the function until `.await` is called? If I didn't want to execute the function yet, I wouldn't have invoked it. Awaiting is a completely different concept than invoking, why overload it? If you want to defer execution of a promise until you await it, you can always do that, but this paradigm forces you to do that. The problem is the…

Are you sure? How would the JavaScript functions execute simultaneously on a single thread? Async is about interleaving computations on a single thread.

Async doesn't have to be single-threaded generally. JavaScript is limited to a single-threaded model, but in other languages (like clojure), futures are tasks run on some other thread. I don't use rust and this article doesn't make any mention of threads so I'm not really sure what's going on here.

Re: Async-await on stable Rust

#52

Earlier quoted context omitted.

Rust isn't only great because it's low level. Things like sum types (called enums in rust), pattern matching and expression orientation mean that it is often much more expressive than other languages for high level code.

ML-inspired languages have all these features too; is the advantage of Rust over those just that it’s more mainstream, the ecosystem is bigger, etc.?

That, and that it has better support for imperative features than most ML languages. You can combine your fancy combinators with mutable variables and for-loops when just want to get something done quickly.

In general, Rust just has all the little details right. It's hard to describe that in concrete terms, but it makes using it a very smooth and satisfying process. I get a similar feeling when using postgres: there's usually a nice way of doing what I want, and I rarely come up against unwelcome surprises.

Re: Async-await on stable Rust

#53
post #30

Isn't it kind of a poor design choice that Rust will not actually begin execution of the function until `.await` is called? If I didn't want to execute the function yet, I wouldn't have invoked it. Awaiting is a completely different concept than invoking, why overload it? If you want to defer execution of a promise until you await it, you can always do that, but this paradigm forces you to do that. The problem is the…

Are you sure? How would the JavaScript functions execute simultaneously on a single thread? Async is about interleaving computations on a single thread.

They're asynchronous tasks, there would be no point in using promises with synchronous tasks. So we're not talking about simultaneous execution of functions that are making use of the single thread, we're talking about serial execution of functions on a single thread which are basically doing nothing more than scheduling an asynchronous task and not bothering to wait for the result.

Think of it this way. I have 3 letters I need to send, and I'm expecting replies for each. A single threaded, synchronous language, would basically send the first letter, wait for the reply, send the second letter, wait for the reply, then send the third and wait for the reply. In JS, you're still single threaded, but you just recognize that there is no point in sitting around and waiting before moving onto the next item. So you send the first letter, and when it would be time to wait, you continue executing code, so you immediately send the next letter, and then finally send the 3rd.

How they're scheduled simultaneously on a single thread is exactly what makes JS so fast for IO. Once it starts making an http call, db call, disk read, etc, it will release the thread to begin execution of the next item in the event loop (which is the structure JS uses under the hood to schedule tasks).

So what really happens is when we call

    asyncA();
    asyncB();
JS will go into `asyncA`, run the code, and at some point it will get to a line that does something like "write this value to the database." This will be an asynchronous behavior, that it knows will be handled with a callback or a Promise, so it will immediately continue execution of the code. So now it pops out of executing `asyncA` and executes `asyncB`, meanwhile the call to the DB has gone out and we don't care if it has finished, we'll await both of these when we need them.

Re: Async-await on stable Rust

#54

Earlier quoted context omitted.

In Rust, you can use a future adapter that does this: futures::join!(asyncTaskA(), asyncTaskB()).await See the join macro of futures[0]. The way it works is, it will create a future that, when polled, will call the underlying poll function of all three futures, saving the eventual result into a tuple. This will allow making progress on all three futures at the same time. [0] https://docs.rs/futures/0.3.0/futures/macr…

"At the same time"? How does that happen on a single thread?

Executors are not inherently single threaded. They can be, they can also not be.

Re: Async-await on stable Rust

#55

Earlier quoted context omitted.

In Rust, you can use a future adapter that does this: futures::join!(asyncTaskA(), asyncTaskB()).await See the join macro of futures[0]. The way it works is, it will create a future that, when polled, will call the underlying poll function of all three futures, saving the eventual result into a tuple. This will allow making progress on all three futures at the same time. [0] https://docs.rs/futures/0.3.0/futures/macr…

"At the same time"? How does that happen on a single thread?

It just interleaves execution. This really seems more similar to python's generator/yield semantics.

Re: Async-await on stable Rust

#56
post #10

How does rust perform in parallel on the same memory? I heard it uses locks? This is not on the same memory right? https://news.ycombinator.com/item?id=21469295 If you want to do joint (on the same memory) parallel HTTP with Java I have a stable solution for you: https://github.com/tinspin/rupy

What do you mean by “on the same memory” exactly?

If you want two threads running in parallel to concurrently access the same memory location you don't need synchronization if you only perform reads, and you need one if there is at least one write. Like in any other language (this comes directly from how CPU works).

The good thing with Rust is that you can't shoot yourself in the foot: if you can't accidentally have an unsynchronize mutable variable accessible from two threads: the compiler will show you an error (unless you explicitely opt out this security by using unsafe primitives, in which case the borrow checker will let you go).

Re: Async-await on stable Rust

#57

I’ve been playing with async await in a polar opposite vertical than its typical use case (high tps web backends) and believe this was the missing piece to further unlock great ergonomic and productivity gains for system development: embedded no_std. Async/await lets you write non-blocking, single-threaded but highly interweaved firmware/apps in allocation-free, single-threaded environments (bare-metal programming wi…

Which executor do you use? Tokio is a bit heavy, no?

Re: Async-await on stable Rust

#58
post #30

Isn't it kind of a poor design choice that Rust will not actually begin execution of the function until `.await` is called? If I didn't want to execute the function yet, I wouldn't have invoked it. Awaiting is a completely different concept than invoking, why overload it? If you want to defer execution of a promise until you await it, you can always do that, but this paradigm forces you to do that. The problem is the…

Are you sure? How would the JavaScript functions execute simultaneously on a single thread? Async is about interleaving computations on a single thread.

Javascript has two differences that contribute here:

* First, it runs the callee synchronously until the first await, which can fire off network requests, etc.

* Second, continuations are pushed onto queues immediately- the microtask queue that runs when the current event handler returns, for example.

Rust does neither of these things:

* Calling an async function constructs its stack frame without running any of its body.

* Continuations are not managed individually; instead an entire stack of async function frames (aka Futures) is scheduled as a unit (aka a "task").

So if you just write async functions and await them, things behave much more like thread APIs- futures start running when you pass a top-level future to a "spawn" API, and futures run concurrently when you combine them with "join"/"select"/etc APIs.

Re: Async-await on stable Rust

#60
post #30

Isn't it kind of a poor design choice that Rust will not actually begin execution of the function until `.await` is called? If I didn't want to execute the function yet, I wouldn't have invoked it. Awaiting is a completely different concept than invoking, why overload it? If you want to defer execution of a promise until you await it, you can always do that, but this paradigm forces you to do that. The problem is the…

In Rust, you can use a future adapter that does this: futures::join!(asyncTaskA(), asyncTaskB()).await See the join macro of futures[0]. The way it works is, it will create a future that, when polled, will call the underlying poll function of all three futures, saving the eventual result into a tuple. This will allow making progress on all three futures at the same time. [0] https://docs.rs/futures/0.3.0/futures/macr…

I don't like this at all. Having to rely on futures::join! means that I don't have the flexibility to control the execution of these things unless Rust adds that specific utility, right?

In JS, for example, the `bluebird` library is a third party utility for managing execution of functions. You can do things like

    const results = await Promise.map(users, user => saveUserToDBAsync(user), { concurrency: 5});
And I pass in thousands of users, and can specify `concurrency: 5` to know that it will be execute no more than 5 simultaneously.

Implementation of this behavior in user space is trivial in JS, is it possible in Rust?

Post reply on HN