Live data from Hacker News

Async-await on stable Rust

blog.rust-lang.org

251–260 of 392 posts

Re: Async-await on stable Rust

#251

Earlier quoted context omitted.

The point is that Rust's borrow checker can't reason about lifetimes very well over function boundaries. It can reason about coarse things that are expressable in the type language, but everything more nuanced than that, such as reasoning about how control flow affects the lifetimes is limited to inside function bodies. The difference between synchronous code and async code implemented as libraries is that async code…

> The point is that Rust's borrow checker can't reason about lifetimes very well over function boundaries. It can reason about coarse things that are expressable in the type language, but everything more nuanced than that, such as reasoning about how control flow affects the lifetimes is limited to inside function bodies. BTW this is a big pain point for me (unrelated to async). Code like this: let ref = &mut self.fi…

Yes, encapsulation sometimes conflicts with the borrowing rules. After all, this is not so surprising: enforcing the borrowing rules requires to follow every concrete access to resources, while encapsulation aims to abstract them away.

Re: Async-await on stable Rust

#252

Earlier quoted context omitted.

Or just use a preemptive scheduler (such as a regular OS scheduler). Or just be explicit, and take difficulties with being explicit as an indication that the data flow is maybe not very well designed. I don't know, maybe there are valid applications for await (such as much frequented web servers, where you might want to have 10s of thousands of connections, that would be too expensive to model as regular threads, but…

await allows to write concurrent (for IO) or parallel (for CPU) code like it was serial. The issue it solves is programmer having trouble executing parallel code in their head, and when relationship became intricate (a computation graph) they just breakdown and write buggy software. A scheduler is targeted at use cases. A preemptive scheduler optimize for latency and fairness and would apply for real-time (say live a…

You can't "avoid state". State is essential to any computation.

The only question is, can you express some of the state-relations as serial code? If "relationships became intricate (a computation graph)", chances are, you shouldn't use serial code anymore, because that splits dependencies in a two-class society: those that are expressed using code and those that are expressed using dead data. It is usually preferable to specify everything as dead data if the relationships get complex, and to then code sort of a virtual machine that "executes" the data.

So it's in fact the simple cases that lend themselves to being expressed as serial code. I won't argue with that there are nice looking example usages. Problem is, as always, systems that help making the simple things easy often make the hard things impossible.

Re: Async-await on stable Rust

#253
post #189

Earlier quoted context omitted.

Erlang probably comes closest?

Not an Erlang user, but my understanding is that the Erlang VM (BEAM) schedules on function calls. Which works fine for that use, since Erlang does looping with tail calls, but is not a solution for procedural languages.

In practice, it's enough to preempt at potentially-recursive function entry and loop backedges. A thread which doesn't recurse or loop has to come to an end pretty quickly, at which point the scheduler will get a go.

Re: Async-await on stable Rust

#254

Earlier quoted context omitted.

>...because it fits their use cases very well and are excited about the release of a big new feature. a bit too excited. GP isn't wrong, Go pretty much has the same thing and I have never seen so much fanboyism for a single feature ever in my career. I don't get it, but that might be because I am a manager.

Go's is a little different. I can't run Go on something with 2k of RAM like an Arduino, but Rust's async structure is actually extra helpful there.

Can Rust's async even work on an Arduino or any bare-metal system?

Re: Async-await on stable Rust

#255

Earlier quoted context omitted.

Not the OP, but Go doesn't have this problem because all I/O is async under the hood, but it exposes a sync interface. This means the entire Go ecosystem is bought into a single concurrency model and runtime, which some find irksome, but it works pretty well most of the time. Of course, Go also lacks Rust's static safety features, but I think that's orthogonal to its concurrency approach.

We tried this in Rust and found it was slower than 1:1 threading.

What you tried wasn't "this", though. It was one particular implementation of lightweight threading that has to cope with Rust's peculiarities, special requirements and compilation targets. There is absolutely nothing essential about lightweight threads that prevents them from emitting essentially the same code as the stackless-coroutine approach. It's just that in Rust it might be very hard or even not worth it, given the language's target audience.

Re: Async-await on stable Rust

#256
post #241

Can anybody share their thoughts on which key features / libs are still missing in Rust?

Binary crates. Sandboxed builds (I'll continue to use crates that have a build.rs which can do anything it wants, but I don't like it). Namespacing crates (a la Java) to deal with the name squatting issue.

Re: Async-await on stable Rust

#257

Earlier quoted context omitted.

There is a maximum number of threads and it's by default set to the # of cores (based on the docs for tokio-executor's ThreadPool and Builder). The docs also say that the # of threads starts at 0 and will increase, so one can do the Scala strategy of starting with large threadpools - one of my projects last year defaulted to 100-200 threads per pool to avoid just this problem. I think the question you're asking is, "…

Rust cannot guarantee the lack of deadlocks or overall thread-safety. It does guarantee no data races, though.

Yes, is there some way I could have been more precise about that in my comment?

Re: Async-await on stable Rust

#258

Earlier quoted context omitted.

> since hot loops can block a whole OS thread Asking as a beginner, what does the above mean? Not sure what does hot loop means, and why does it block Os thread

Go creates the illusion of preemptive multithreading by having implicit safe-points for cooperative multithreading. Each IO operation is such a safe-point. If you write an infinite loop like `for {}` where there are no IO operations in loop body, it will block indefinitely. This will prevent the underlying OS thread from being available to other goroutines. The same thing can happen even if you do have IO operations…

Note that this is being fixed in the next release: https://golang.org/issue/10958

Re: Async-await on stable Rust

#259
post #255

Earlier quoted context omitted.

We tried this in Rust and found it was slower than 1:1 threading.

What you tried wasn't "this", though. It was one particular implementation of lightweight threading that has to cope with Rust's peculiarities, special requirements and compilation targets. There is absolutely nothing essential about lightweight threads that prevents them from emitting essentially the same code as the stackless-coroutine approach. It's just that in Rust it might be very hard or even not worth it, giv…

Fibers under the magnifying glass [1] might be a relevant paper here. Its conclusion, after surveying many different implementations, is that lightweight threads are slower than stack less coroutines.

[1]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p136...

Re: Async-await on stable Rust

#260
post #254

Earlier quoted context omitted.

Go's is a little different. I can't run Go on something with 2k of RAM like an Arduino, but Rust's async structure is actually extra helpful there.

Can Rust's async even work on an Arduino or any bare-metal system?

Yes. Right now the implementation requires TLS but that will be going away.
Post reply on HN