Live data from Hacker News

Async-await on stable Rust

blog.rust-lang.org

301–310 of 392 posts

Re: Async-await on stable Rust

#301

Earlier quoted context omitted.

Not much doc at the github. Can you provide a quick overview?

Not much I can say other than “an executor designed specifically for embedded.” I don’t do embedded dev myself, so it’s more of a curiosity thing for me than something that I can give you a lengthy explanation of.

Embrio provides only a very limited executor. it can just drive only single Future. Which gets re-polled every time a certain system interrupt occurs. You can obviously have subtasks of that single task (e.g. via join! and friends), but you can't have other dynamic tasks.

jrobsonchase has implemented a more dynamic solution which uses custom allocators for futures: https://gitlab.com/polymer-kb/firmware/embedded-executor

I think there might also be other solutions out there. I remember the Drone OS project also doing something along that.

Re: Async-await on stable Rust

#302

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?

I'd like to hear more about this - I thought Tokio was just some tools on top of MIO which is just `select` (or similar). Is Tokio heavy?

Re: Async-await on stable Rust

#303
post #255

Earlier quoted context omitted.

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…

I don't understand what your objection is. It's a given that what I wrote applies to Rust. This is a thread about Rust. I didn't say that M:N threading is always slower than 1:1. Besides, fibers don't emit essentially the same code as async code. One has a stack, and the other doesn't. That's a significant difference.

If the stack could be sufficiently small, it's not that different from heap allocated async state. But you probably needs segmented stacks, or at least separate stack async preemptible or non-async-preemptible code (has anyone tried making a system like this?)

Re: Async-await on stable Rust

#304

Earlier quoted context omitted.

How exactly do I write embedded code for a tiny chip on a different architecture with just 4K of RAM and no OS that uses the Win32 fibers?

Probably not using green threads / async at all? That would require a number of stacks as well as a little runtime, which will quickly eat up your 4K.

Just to clarify for those following along, Rust async code does not use green threads and doesn't require a stack per task.

Re: Async-await on stable Rust

#305

Earlier quoted context omitted.

But whether a function is not async-safe is pretty black and white (i.e. there's a lot of clearly unsafe code). Even a definition as simple as "performs blocking I/O" would be extremely helpful. This is the value people get out of async only environments like node. Yes, you still have to worry about costly for loops but I don't have to worry about which database driver I'm using because they are all async. In a mixed…

What about long-running computations? They're not really async-safe (they will block the thread), but they don't perform any IO.

I think the suggestion is “clearly blocking io should be marked as such (with some marker like unsafe) and other functions can be marked “blocking” if the creator decides it is blocking.”

In the worst case a problem could still occur, but once found, the “problem” function can be marked appropriately. At the least that would start to solve the issue.

Re: Async-await on stable Rust

#306

Earlier quoted context omitted.

I've dipped my toes into embedded rust from time to time. Can you give me an example or two of how you would use async/await in an embedded environment? I'm just curious about how it would work.

Another infrequent toe dipper here - say you need to send some command to a peripheral, wait for the device to acknowledge it, then send more data. The naive implementation would poll for the interrupt or just go to sleep, meaning no other user code can run in that time. A naive async implementation would spread your code all over the place - it wouldn't just be a function call with three statements. There are librar…

>poll for the interrupt

Errr, no. You either poll, or set up an interrupt to catch an event. The point of an interrupt is to allow other code to continue to run while waiting for a peripheral.

Re: Async-await on stable Rust

#307
post #286

Earlier quoted context omitted.

Go is even more different. Rust async has explicit yields with await, but Go does it implicitly at various key locations. This is actually pretty surprising to many folks, it was in the past and maybe still is possible to deadlock Go with a certain incantation of tight looping. Another difference with Rust is that async functions are stackless. Go has to contend with having a non-conventional stack and interoperabili…

> [...] Go does it implicitly at various key locations. This is actually pretty surprising to many folks, it was in the past and maybe still is possible to deadlock Go with a certain incantation of tight looping. This is being worked on here: https://github.com/golang/go/issues/24543

Fascinating. This would make Goroutines one giant leap closer to being thread-like. It feels weird how much of the OS scheduler is being “duplicated” but you can’t really argue much with the results.

Re: Async-await on stable Rust

#308

Does Rust offer composable futures ? Something like Javas CompletableFuture or Clojure's https://github.com/leonardoborges/imminent ?

Yes you can use functions like CompletableFuture’s thenApply.

However, Rust Futures have a very different implementation compared to CompletableFuture.

Re: Async-await on stable Rust

#309
post #98

This is a big improvement, however this is still explicit/userland asynchronous programming: If anything down the callstack is synchronous, it blocks everything. This requires every components of a program, including every dependency, to be specifically designed for this kind of concurency. Async I/O gives awesome performance, but further abstractions would make it easier and less risky to use. Designing everything a…

The alternative is to write SansI/O code (https://sans-io.readthedocs.io/), so that your program don't have to think about that.

Besides, you don't have to put async/await everywhere: if your code is not performing IO, it completely ignore this concern.

The problem is that most of your code is mixing I/O and non I/O code, and people just don't think about it. E.G: a django website is not just a web server, but has also plenty of calls to the session store, the cache backend, the ORM, etc.

Now you could argue that the compiler/interpreter is supposed to hide the sync/async choice to the code user. Unfortunately, this hides where the concurrency happens, and things have dependencies on each others. Some are exclusive, some must follow each others, some can be parallel but must all finish together at some points, some access concurrent resources...

You must have control over all that, and for that to happen, you can either:

- have guard code around each place you expect concurrency. This is what we do with threads, and it sucks. Locking is hard, and you always miss some race condition because it can switch anywhere. - have implicit but official switch points and silos you must know by heart. This is what gevent does. It's great for small systems, not so much at scale. - have explicit switch points and silos: async/await, promises, go-routine. This is tedious to write, but the dangerous spots are very clear and it forces you to think about concurrency upfront.

The last one is the least worse system we managed to write.

Re: Async-await on stable Rust

#310
post #98

This is a big improvement, however this is still explicit/userland asynchronous programming: If anything down the callstack is synchronous, it blocks everything. This requires every components of a program, including every dependency, to be specifically designed for this kind of concurency. Async I/O gives awesome performance, but further abstractions would make it easier and less risky to use. Designing everything a…

They do, but only at the expense of interoperability. Any "green thread" solution breaks down once you have to invoke code written in something else while allowing it to call you back. Async futures, on the other hand, can map to any C ABI with callbacks.

So until there's some standardized form of seamless coroutines on OS level, that is sufficiently portable to be in wide use, we won't see widespread adoption of them outside of autarkic languages and ecosystems like Erlang or Go.

Post reply on HN