Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Yes rust async isn’t good imo. You can do basically the same thing with stackfull coroutines.

Also the ecosystem is setup so you have to use tokio and everything has to be an Arc.



No, stackful coroutines requires a runtime. Not going to work on embedded, which is where async rust shines the strongest.

If you don't care about embedded that is fine. But almost all systems in the world are embedded. "Normal" computers are the odd ones out. Every "normal" computer has several embedded systems in it (one or more of SSD controller, NIC, WiFi controller, celular modem, embedded controller, etc). And then cars, appliances, cameras, routers, toys, etc have many more.

It is a use case that matters. To have secure and reliable embedded systems is important to humanity's future. We need to turn the trend of major security vulnerabilities and buggy software in general around. Rust is part of that story.


A stackfull coroutine is brittle and doesn't compose as cleanly as stackless coroutines. As a default language primitive, the latter is almost always the robust choice. Most devs should be using stackless coroutines for async unless they can articulate a technical justification for introducing the issues that stackfull coroutines bring with them.

I've implemented several stackfull and stackless async engines from scratch. When I started out I had a naive bias toward stackfull but over time have come to appreciate that stackless is the correct model even if it seems more complicated to use.

That said, I don't know why everyone uses runtimes like tokio for async. If performance is your objective then not designing and writing your own scheduler misses the point.


> You can do basically the same thing with stackfull coroutines.

It's clear that you don't understand the use cases that async in Rust was designed to accommodate.

> Also the ecosystem is setup so you have to use tokio and everything has to be an Arc.

It's clear that you're not at all familiar with the Rust async ecosystem, including Embassy.


I understand what that is but I just don’t care. I am guessing the vast majority of people using rust also don’t care. Justifying the decision to create this mess by saying it is for embedded makes no sense to me.

Also don’t understand why you would use rust for embedded instead of c


Embedded systems vastly outnumber classical computers. Every classical computer has several embedded systems in them. As does appliances, cars, etc. So yes they are an incredible important use case to secure our modern infrastructure.


> You can do basically the same thing with stackfull coroutines.

...Minus the various tradeoffs that made stackful coroutines a nonstarter for Rust's priorities. For example, Rust wanted:

- Tight control over memory use (no required heap allocation, so segmented stacks are out)

- No runtime (so no stack copying and/or pointer rewriting)

- Transparent/zero-cost interop over C FFI (i.e., no need to copy a coroutine stack to something C-compatible when calling out to FFI)


"Tight control over memory use" sounds wrong considering every single allocation in rust is done through the global allocator. And pretty much everything in rust async is put into an Arc.

I don't understand what kind of use case they were optimizing for when they designed this system. Don't think they were optimizing only for embedded or similar applications where they don't use a runtime at all.

Using stackfull coroutines, having a trait in std for runtimes and passing that trait around into async functions would be much better in my opinion instead of having the compiler transform entire functions and having more and more and more complexity layered on top of it solve the complexities that this decision created.


> "Tight control over memory use" sounds wrong considering every single allocation in rust is done through the global allocator.

In the case of Rust's async design, the answer is that that simply isn't a problem when your design was intentionally chosen to not require allocation in the first place.

> And pretty much everything in rust async is put into an Arc.

IIRC that's more a tokio thing than a Rust async thing in general. Parts of the ecosystem that use a different runtime (e.g., IIRC embassy in embedded) don't face the same requirements.

I think it would be nice if there were less reliance on specific executors in general, though.

> Don't think they were optimizing only for embedded or similar applications where they don't use a runtime at all.

I would say less that the Rust devs were optimizing for such a use case and more that they didn't want to preclude such a use case.

> having a trait in std for runtimes and passing that trait around into async functions

Yes, the lack of some way to abstract over/otherwise avoid locking oneself into specific runtimes is a known pain point that seems to be progressing at a frustratingly slow rate.

I could have sworn that that was supposed to be one of the improvements to be worked on after the initial MVP landed in the 2018 edition, but I can't seem to find a supporting blog post so I'm not sure I'm getting this confused with the myriad other sharp edges Rust's sync design has.


> > And pretty much everything in rust async is put into an Arc.

> IIRC that's more a tokio thing than a Rust async thing in general. Parts of the ecosystem that use a different runtime (e.g., IIRC embassy in embedded) don't face the same requirements.

Well, if you're implementing an async rust executor, the current async system gives you exactly 2 choices:

1) Implement the `Wake` trait, which requires `Arc` [1], or

2) Create your own `RawWaker` and `RawWakerVTable` instances, which are gobsmackingly unsafe, including `void*` pointers and DIY vtables [2]

[1] https://doc.rust-lang.org/std/task/trait.Wake.html

[2] https://doc.rust-lang.org/std/task/struct.RawWaker.html


Sure, but those are arguably more like implementation details as far as end users are concerned, aren't they? At least off the top of my head I'd imagine tokio would require Send + Sync for tasks due to its work-stealing architecture regardless of whether it uses Wake or RawWaker/RawWakerVTable internally.

I find it interesting that there's relatively recent discussion about adding LocalWaker back in [0] after it was removed [1]. Wonder what changed.

[0]: https://github.com/rust-lang/libs-team/issues/191

[1]: https://github.com/aturon/rfcs/pull/16


You can do rust async by moving instead of sharing data, for example




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: