Live data from Hacker News

Why asynchronous Rust doesn't work

eta.st

141–150 of 305 posts

Re: Why asynchronous Rust doesn't work

#141

Honestly, people want to write high level code in low level languages too often. Both Rust and C++ ought to be relegated to high performance cores of larger, "squishier" programs written in higher level languages. The Emacs model is perfect for most programs running on conventional systems. The key insight here is that garbage collection gives you access to a variety of patterns that are otherwise fiendishly difficul…

> Both Rust and C++ ought to be relegated to high performance cores of larger, "squishier" programs

So, people from Google have explained about this before. The idea you have assumes that if you speed profile the code, 99% of samples land in this function "A()" and so you just re-write that part in C++ and now it's faster, or if you measure allocations you find 99% of RAM was allocated by "B()" and so you just re-write that part in C++ and now it uses less RAM.

Google already did all that low-hanging fruit. When they run the profile it comes back flat. You should rewrite A, B, D, E, F, J, K, L, M, N ... in other words the way to make the system faster is to just write it in C++

Part of this is also scale. If a system I run once week is a little slow, maybe in some sense that costs 40¢ but I don't account for it. At a mid-size non-IT firm maybe a similar performance cost is $1000 per year. Just about worth somebody enquiring if it can be sped up, but not worth arguing about it if the answer is "No". Maybe a mid-size IT firm where you work spends $1k per month on this problem. You could speed it up by rewriting the whole system, this would take some time - how many days work before it's cheaper to leave the problem than pay you to fix it? However, at Google's scale maybe that problem costs them $1M per week. They can justify assigning a whole team to fix that because of scale.

Re: Why asynchronous Rust doesn't work

#142
post #108

Earlier quoted context omitted.

> GC pauses, Rc does not, it's simply a deallocation by the last reference holder There are pauseless GCs (e.g., Azul for JVM), and Go kicked off a trend of super-low-latency GC. Also, RC deallocation is O(N) while GC is usually O(1) (ignoring pedantry about how RC is a type of GC). Further, RC can't handle cycles automatically. > Rc still has predictable memory allocation/deallocation, GC is not guaranteed to run un…

> RC deallocation is O(N) What is N here? Number of allocations?

Yes.

Re: Why asynchronous Rust doesn't work

#143
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

Sorry to spoil your axe-grinding with hard data, but the Rust async ecosystem has exploded since 2019. It is now about 5-6 times larger than it was before async/await landing:

https://lib.rs/crates/tokio/rev

And Rust as a whole keeps growing exponentially:

https://lib.rs/stats

Re: Why asynchronous Rust doesn't work

#144

Earlier quoted context omitted.

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

Are there any good resources for design patterns in Rust? I've gone through Rust by example and am writing mid-size rust programs now but would love to check my work against the experts.

There's The Unofficial Rust Design Patterns Book...

https://rust-unofficial.github.io/patterns/

(More generally, there's the Little Book of Rust Books to find things like that: https://lborb.github.io/book/ )

...and someone asked about good code to learn from on Reddit a day or two ago and was advised to read basically any code by dtolnay or burntsushi, two of the big wizards who feel like they've written half the Rust ecosystem at times.

Re: Why asynchronous Rust doesn't work

#145
post #9

The author spends the majority of the post saying how synchronous Rust doesn't work. The main problem? Closures have to be passed as traits. And they either don't know about the `f: impl Fn(i32)` syntax or refuse to use it for some reason. Then the last paragraph just say "Oh and asynchronous Rust is even worse."

In synchronous Rust, closures (largely) don’t need to have asynchronous lifetimes. You really don’t have to think about them all that much.

Re: Why asynchronous Rust doesn't work

#147

Earlier quoted context omitted.

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!

As I remember, it uses an evolution of Objective-C's Automatic Reference Counting feature.

Re: Why asynchronous Rust doesn't work

#148
post #131

Can someone explain to me the attraction of async programming? I don't really do JS, where a lot of this seems to be happening, but the code I have seen with the huge ladders of callbacks doesn't seem so great to work with to me. Also, although using promises seems better, it seems like it could quickly become spaghetti.

If you mean non-blocking in general, the benefit is that your system can do something else useful while it's waiting for some operation to complete (usually things accessing files or a database or a network service) If you specifically mean async/await syntax, let me illustrate with a contrived example. It can let you express a sequence of asynchronous operations in a more natural way: function promised(cache, db, me…

It's not that I don't see the benefit of the CPU doing something useful when waiting for I/O, my confusion comes from the fact that people like to express this using promises/await.

Why not just arrange it like this?

    function non_awaited(cache, db, metrics) {
        let result = cache.query(...);
        if (!result) {
          result = db.query(...);
          cache.store(result);
        }
        metrics.log(...);

        return result;
      }
    
Basically doesn't a good threading library just allow you to make all those 'awaits' implicit?

I mean just because await isn't explicitly there, if I run the function above in a thread, my understanding is that the thread does yield to other threads while waiting for I/O.

It's not as if it busy-loops while waiting or something.

Re: Why asynchronous Rust doesn't work

#149

Can someone explain to me the attraction of async programming? I don't really do JS, where a lot of this seems to be happening, but the code I have seen with the huge ladders of callbacks doesn't seem so great to work with to me. Also, although using promises seems better, it seems like it could quickly become spaghetti.

Leveraging multiple threads can allow your program to get more done, and if it's a graphical application you can also reduce blocking in the UI thread to an absolute minimum.

Re: Why asynchronous Rust doesn't work

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

I don't use Rust but was curious if this was a real or imagined problem--it seems to be the latter. Two points:

1. the example could have made a pure callback function that takes a mut& db param and pass thaf param to the 'do'er function. Why is this not required anyway? i.e. How does Rust know/decide who owns the mut& db if both the closure and the function that creates the closure can reference it?

2. as mentioned, the complaints about async seems to apply to closures in general even if used synchronously, AFAICT.

Best to think of this post as quirks when working with closures in Rust. It would have been far better to list each with workarounds.

Post reply on HN