Live data from Hacker News

Why asynchronous Rust doesn't work

eta.st

51–60 of 305 posts

Re: Why asynchronous Rust doesn't work

#51
post #13

Excellent post. Async ruins everything even in GC languages. It's just making things needlessly hard for programmers in an attempt to save effort from computers. Erlang shows how to do massive scales of slow IO if you really need it (most programs don't).

> It's just making things needlessly hard for programmers in an attempt to save effort from computers. Well actually it is supposed to make concurrency easier for programmers. What would you say is an "easy" way to deal with concurrency? Handle threading, memory visibility issues, locking, etc yourself? Doing it "reactive"? I guess personally I too would say something messaging based such as the actor pattern but not…

How does async prevent anything about memory visibility and locking issues? Afaik only immutability and borrow-checker-like solutions can prevent data races (but not race conditions!).

Re: Why asynchronous Rust doesn't work

#52
post #7

The article glosses over async Rust and is mostly a rant about how closures are difficult in Rust. Most of the difficulty comes from Rust not having a GC yet wishing to keep track of object lifetimes precisely: a GC'ed language needs no distinction between an ordinary function pointer and a closure that captures the environment. But Rust being a low-level systems language chose not to have a GC. Another popular langu…

From my very limited expeirience with Rust I noticed that it becomes way more easy and laid back language when you just skip using references and lifetimes nearly completely and just wrap everything in Rc . Then you are getting expeirience of fairly high level language with a lot of very cool constructs and features like exhaustive pattern matching and value types with a lot of auto-derived functionality. Does Rc hel…

`Rc` freezes the value as long as it's shared unless you use interior mutability. It's fine when you want to share immutable data, but if you ever need to mutate its contents you will have to deal with awkward cases and situations, and at runtime!

Wrapping everything in `Rc` is not a good default strategy. Instead figure out an architecture that works well with the borrow checker! This normally means thinking hard about your data structures and the ownership model of your application.

I love Rust precisely because of this. You can leverage the compiler to drive your development and design. If it's hard, then it's probably wrong!

Re: Why asynchronous Rust doesn't work

#53
post #26

Maybe it’s only my take, but from what I understand, the author wants to easily create closures with mutable references and call them from anywhere, asynchronously? And the complaint is that Rust semantics makes this hard. Well yes, Rust makes it uncomfortable to shoot your own foot, that’s kind of the point.

That was my impression too. Rust “makes it hard” for a reason: it’s not safe. If you work with the type system to prove that it is, you can go about and do your thing but Rust is about guarantees. That’s one great thing about it. You can’t ask it to just not guarantee something.

Re: Why asynchronous Rust doesn't work

#54
post #26

Maybe it’s only my take, but from what I understand, the author wants to easily create closures with mutable references and call them from anywhere, asynchronously? And the complaint is that Rust semantics makes this hard. Well yes, Rust makes it uncomfortable to shoot your own foot, that’s kind of the point.

Why would the first example with the database be "shooting your own foot"? I'm not a Rust dev, but in other languages that code makes perfect sense to me.

Rust has &mut references and & references.

The `&mut Database` sort of implies that the Database handle doesn't do its own locking or other needed state tracking - it just relies on the exclusivity of `&mut` in Rust to be sure that nobody else is modifying the database handle at the same time.

If the API used `&Database`, then it would have to be more flexible for simultaneous use of the handle. And then the closure would be (a bit) easier to call too, because it's not tracking that exclusive reference.

If the API used a reference counted `Database` handle, then it would release even more restrictions of lifetime management, etc. You can implement all of these in Rust.

In other languages, you usually end up with alternative two or three.

If you try to simultaneously take alternative 1 and use it in a way that's not supported, that would be shooting yourself in the foot. Except Rust says compile error instead.

Re: Why asynchronous Rust doesn't work

#55
post #32

Earlier quoted context omitted.

Async is bread and butter of JS and you rarely have any larger bits of sync code, so you learn to deal with this. And then being able to just freely pass bits of data accessing code (closures) around is such wonderful feeling that you'll miss it everywhere else you go. I recently had a little excursion into Python and had to invent a very nasty hack to concisely keep short bits of code accessible through some constan…

Frontend or backend js? Because in the frontend everything is just scheduled to a single thread, so you only deal with concurrency, not parallelism.

In node.js backends, you also deal with a single thread only; if you want multiple CPUs, you'd need node-cluster, giving you, conceptually speaking, multiple shared-nothing single-thread environments to load-balance requests into. Technically, libuv (the C lib exposing async I/O to node) uses threads but that is hidden away from you. Multithreading in JS can't work anyway since JS doesn't have synchronization primitives, which is both a blessing (because it drastically simplifies the design space for the language ie no JVM-like happens-before constraints, atomic ops, and "synchronized" heisenbugs) and a curse (because most backend/business code doesn't benefit at all from async and its terrible debugging story, and you need to fork out into workers/isolates for even slightly CPU-heavy things).

Re: Why asynchronous Rust doesn't work

#56
post #26

Maybe it’s only my take, but from what I understand, the author wants to easily create closures with mutable references and call them from anywhere, asynchronously? And the complaint is that Rust semantics makes this hard. Well yes, Rust makes it uncomfortable to shoot your own foot, that’s kind of the point.

Maybe it’s only my take, but from what I understand, the author wants to easily create closures with mutable references and call them from anywhere, asynchronously?

I think you are misunderstanding the author's point. I think that they'd probably agree that the (lack of) ergonomics of closures are a necessary result of the safeguards that Rust provides.

They point is more that, given that closures have somewhat frustrating ergonomics, it was probably a bad choice to base Rust's primary concurrency system on closures.

Disclaimer: this is not my opinion, just paraphrasing what I believe the author's point is. I found the post a bit strange, it seems to end rather abruptly. It doesn't seem to address the main question it seems to raise: what does this mean for async Rust and why is this bad?

Re: Why asynchronous Rust doesn't work

#57
I don't have any experience with async Rust (but I stuggled a lot with Rust's closures when I dabbled with Rust a while back so I can at least feel the pain the article tries to convey), but one important reason to not build async-await on top of fibers or threads but instead on code transformation (aka 'compiler magic') is 'weird architectures' like WASM, which doesn't have easy access to threading (locked behind COOP/COEP headers), and where the call stack is inaccessible to code running inside the VM.

I didn't quite get the gist of the article though, isn't the whole point of async-await to get rid of passing callback function pointers around? What do closures have to do with async-await in Rust?

Re: Why asynchronous Rust doesn't work

#58
post #32

Earlier quoted context omitted.

Async is bread and butter of JS and you rarely have any larger bits of sync code, so you learn to deal with this. And then being able to just freely pass bits of data accessing code (closures) around is such wonderful feeling that you'll miss it everywhere else you go. I recently had a little excursion into Python and had to invent a very nasty hack to concisely keep short bits of code accessible through some constan…

Frontend or backend js? Because in the frontend everything is just scheduled to a single thread, so you only deal with concurrency, not parallelism.

It's still concurrency in Node, since there's no threads in JS.

There's the `worker_threads` (never used it though) which is like web workers in a browsers, but those work by posting messages to eachother.

Re: Why asynchronous Rust doesn't work

#59
post #5

I’m not an expert by async rust seems to work pretty well to me. I guess I’ll have to become an expert to find my disappointment.

Which part of the article are you disagreeing with? Just the title?

The article complains about how hard it is to pass closures with references - which is a valid criticism; I run into that as well and while you can fix it, it's not as straightforward and as documented as it should be.

It doesn't have much to do with async, despite the title. Async works just fine.

Re: Why asynchronous Rust doesn't work

#60
post #44

> As someone who used to really love Rust, this makes me quite sad. The current async story is still an MVP and I too dislike it. In the months before async, the ecosystem seemed on halt, waiting for async to land on stable Rust. Since then nothing has changed. The ecosystem "degraded" noticeable and has not recovered since. Maybe in future async will be great, but right now I try to avoid it. ... I still love Rust

I think your comment hits the bullseye better than many others I've seen around this. It very much looks like the language stopped progressing with async.

Seems like they just tried to be everything at once, and reached some sort of a critical mass. It probably didn't help how Mozilla dropped lots of their Rust projects and staff at roughly the same time.

It's still a very good C++ replacement. I think its role as a higher level application language is more of an open question.

Post reply on HN