Live data from Hacker News

Why asynchronous Rust doesn't work

eta.st

31–40 of 305 posts

Re: Why asynchronous Rust doesn't work

#31

Earlier quoted context omitted.

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…

If you are going to wrap everything in Rc, just use kotlin or c-sharp or python?

And suffer a 100 MB runtime?

If anything, Rust with refcounts for everything is much closer to Swift.

Re: Why asynchronous Rust doesn't work

#32
post #12

Earlier quoted context omitted.

It’s a pain with GC as well, coming from a C# background. It’s incredibly easy to write something that intermittently doesn’t work in weird and impossible to debug ways.

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.

Re: Why asynchronous Rust doesn't work

#33
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…

You probably need Arc in the context of async, but if it's a normal closure, Rc will do.

However, that's not needed always. You largely wanna move stuff into closures in my experience, since the closure ends up owning the data.

Arc comes with a small performance overhead (Rc too, but less so I think?), so you don't want to use it all the time. When using Arc, you'll usually need a Mutex too, which adds its own cost, etc.

There are ways to partially avoid this costs, but they can add complexity (eg channels).

Sometimes you might be able to use an Async-flavor of the synchronization types instead, which come with more acceptable performance compromises in Async contexts.

Re: Why asynchronous Rust doesn't work

#34
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…

As he mentioned Erlang he probably finds the actor model easier.

Threads and queues are pretty easy to reason about too — just avoid locks and shared memory.

Re: Why asynchronous Rust doesn't work

#35
post #20

Earlier quoted context omitted.

Hold on now. Even in GC’ed languages? Which ones? It is another programming paradigm. It has its uses. It has its drawbacks. “Ruining everything” is a big stretch.

It's really bad in Python, because the baseline awaitable of Python is a coroutine — same as Rust but without compiler support. The issue of coroutine-based async is that a coroutine does not do anything until it's awaited (and the chain goes up to the reactor), so in Python when you create a coroutine nothing happens. This is unlike Javascript or C# (IIRC) where the baseline awaitable is a task , with tasks awaiting…

No one believes that Python does it correctly.

Re: Why asynchronous Rust doesn't work

#36
post #24
post #20

Earlier quoted context omitted.

Hold on now. Even in GC’ed languages? Which ones? It is another programming paradigm. It has its uses. It has its drawbacks. “Ruining everything” is a big stretch.

Eg Python, Clojure, JS all have no-fun async io modes. It has uses but should be kept in a box that most users can ignore, like Python and Clojure do.

Python async is certainly not in a box — it's invading the language everywhere and it's terrible.

Re: Why asynchronous Rust doesn't work

#37

Earlier quoted context omitted.

> 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…

> What would you say is an "easy" way to deal with concurrency? The Beam/Erlang/Elixir model. It's a bit more constraining but it's just so clean and reliable, and processes having individual mailboxes makes it much simpler than having to wonder what synchronisation primitives to use, then decide how to share them (globals? parameters? others?). Just get a reference to a process and you can send it messages, simple.…

> The Beam/Erlang/Elixir model. It's a bit more constraining but it's just so clean and reliable [..]

I agree. But I think that only works if you embed it in the language like Erlang did. If you make it optional you get libraries which use different models, people still making concurrency mistakes, etc.

But for more generic languages then Erlang such as Rust (or Java, C#, etc.) this simply isn't an option. Because the actor pattern is too opinionated to be a fix for all.

Re: Why asynchronous Rust doesn't work

#38
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…

When async is visible in the type system it means you need to write things like iterating containers twice: once for dealing with non-async values, and a second time for handling async operations.

Well maybe this isn't the best example because you already have iterators for the plain iteration part; however let's say you wanted to make an iterator for a container that needs async to iterate the data, then you find yourself having the same problem that the existing facilities making use of the old "non-async" iterators become useless.

Alternatively you let async leak into _everything_, even if they are not actually using async themselves.

There's nothing wrong with runtime-driven schedulers handling the threads for you, but async isn't the only way to do it. But it is one of the easy ways to do it and a way that is implementable as a library.

In particular single-threaded async (javascript) can be painful because you need to be mindful about not doing anything for "too long" without splitting the work into several parts. In a sense with async we're back in the era of co-operating scheduling. Even in multi-threaded environment is can be based on luck or faith that not all the threads allocated happen to get stuck on long-running jobs when short and fast user-facing interactive async tasks are starving. (A problem solved by over-allocating threads of course.)

Re: Why asynchronous Rust doesn't work

#39
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.

Re: Why asynchronous Rust doesn't work

#40

Earlier quoted context omitted.

If you are going to wrap everything in Rc, just use kotlin or c-sharp or python?

And suffer a 100 MB runtime? If anything, Rust with refcounts for everything is much closer to Swift.

Ah didnt realize swift has no runtime. Thanks!
Post reply on HN