Live data from Hacker News

Why asynchronous Rust doesn't work

eta.st

211–220 of 305 posts

Re: Why asynchronous Rust doesn't work

#211
post #16

Have to day, mixing async and CPU intensive code (I’m using Rust because it is good at CPU intensive code!) has been a frustrating experience, with lots of noise and baggage associated with spawn_blocking to make things run well.

I have had great luck using rayon for distributing CPU intensive work across available cores. If you are doing I/O I can see why async is preferable but rayon is an excellent library for parallel work.

I have found that async or even in Go with goroutines, a large amount of small threads are not faster even if they should be in theory when it comes to CPU intensive work.

I use it to generate a 3D universe (at the atomic level) but store the data as enums.

Here is the repo: https://github.com/selfup/oxidizy

Big help from rayon:

1) https://github.com/selfup/oxidizy/blob/master/crates/unigen/...

2) https://github.com/selfup/oxidizy/blob/master/crates/unigen/...

3) https://github.com/selfup/oxidizy/blob/master/crates/unigen/...

Example perf generating an obscene amount of data on a 32GB machine with 16 threads (3800x):

Atoms: 110592000 Baryons: 26099712000 Quarks: 78299136000

real 0m12.779s user 0m0.000s sys 0m0.000s

Re: Why asynchronous Rust doesn't work

#213
post #203
post #199

"Maybe we could just have kept Rust as it was circa 2016, and let the crazy non-blocking folks write hand-crafted epoll() loops like they do in C++. I honestly don’t know, and think it’s a difficult problem to solve." I think this is the most underappreciated part of this article. Since when did everything have to be async? There are other ways to represent concurrency that more accurately reflect what the computer i…

> but the task of converting a high-level workstream into a state machine could be automated by the tooling That tooling is literally async/await. async/await transforms functions into state machines

Except doing so introduces a bunch of needless programming difficulties, including but not limited to the ones discussed in this article. For example, if you make the state machines and epoll loop explicit, you don't have the function coloring problem -- all your I/O requests from state machines to the poll loop (which may or may not cross thread boundaries) are explicit synchronization points with your global business logic, which gives you fine-grained control over how your state machines handle things like request timeouts, resource quota limits, cancellations, execution suspend/resume, and so on. As another example, you're not limited to factoring your state transitions into closures. As a third example, your business logic would have global, explicit control over I/O scheduling, which greatly simplifies end-to-end QoS and request prioritization.

Re: Why asynchronous Rust doesn't work

#214
post #15

It was heavily discussed previously. In particular, it triggered this response from Rust contributor withoutboats: https://news.ycombinator.com/item?id=26410487 And this blog post from someone who did spend a lot of time working with async rust: https://tomaka.medium.com/a-look-back-at-asynchronous-rust-d...

Oh, thanks for that link. Withoutboats is being quite emotional, but it is understandable to be emotional about their brain child. I am tempted from time to time to try Rust, but in the end, I don't think it provides enough benefits for me to consider it. I like high-level, and when I am going low-level, I don't want to be hand-cuffed. It seems with Rust, I am paying all the time just for the ability to go into hand-…

I am sort of in the same boat. I use C++ for server type applications. I consider modern C++ safe enough. While there are no explicit safety guarantees I am a practical man. My servers work for years without any complaints from clients. No memory leaks, no crashes. That's the end result and I think from that perspective for me using Rust would be ROI negative as I would have to port / replace a lot of code I reuse in my various products.

Things of course would be different should the client insist on implementation done in Rust but so far not a single client of mine ever mentioned using this language.

Re: Why asynchronous Rust doesn't work

#215
post #192

Earlier quoted context omitted.

Zig managed to get async correct, if you ask me, but it's because I would call it "the lowest-level primitive to do what you need it to do" (shift the function frame over to a place that "might not be the stack"). If you think of it as a sugared "async" you will probably do it wrong. After a lot of wrassling with it, once I realized that it was a very shallow abstraction over what the hardware is actually doing, ever…

Zig's approach is really nice here, but it's also a notably easier problem to solve than rust has, since it's not trying to solve for parallel/concurrent safety. Do you think Zig's approach would be feasible in Rust? I guess maybe you could do it, but the sync version would have to have the stricter constraints of the async version.

I'm holding out for formal-methods based static analysis on lifetimes in zig.

Re: Why asynchronous Rust doesn't work

#216

Earlier quoted context omitted.

I'd say seat belts more than handcuffs. When going low level it's easy to slip in memory leaks and security vulnerability. If you care about developer speed and security but don't care about correctness or performance you can rely on someone's else implementation and write higher level code (eg. use node and offload low level security considerations to node). If you care about developer speed and performance but don'…

> To be frank I find the point about developer speed in Rust to be a bit exaggerated, it's pretty high level and the tooling is pretty great. Rust has a long learning curve that most people won’t make it through. For them, they might feel the language is slow to developenin because they haven’t gotten to the point where they are “thinking” in Rust. As a Haskeller, you are well suited to learn Rust; due to their simil…

That's an interesting take on Rust. Given that I have written a lot of code in Standard ML, I might give Rust a try after all.

GP's statement "If you care about security, correctness and performance but don't care about developer speed, use Rust." threw me a little off here. Because, Standard ML is very quick and easy to develop in. So should Rust not inherit that property?

Re: Why asynchronous Rust doesn't work

#217
post #201

Earlier quoted context omitted.

How so? Obviously you can build an unsafe IPC mechanism with concurrent access, label it "safe" when it isn't, and then say "Look at this horrible mess, I blame Rust" but it seems like it'd be faster to just implement std::ops::Index unsafely and then blame Rust because thing[len+1] blew up even though Rust has "memory safety". Now I'm going to write an amusing aside. One way you could get into this trouble is if you…

Because as explained on rustnomicon, there are many ways to access data in parallel ways, and the language only prevents a tiny subset of those cases. However almost every time data races and Rust come together in the same sentence it is as if it would prevent all use cases.

But (unless you've got an excerpt that says otherwise) the Rustonomicon is about unsafe Rust. And I was explaining that safe Rust has data race freedom.

The Rustonomicon is not warning you about scary hidden problems in safe Rust, it's warning you about scary problems you need to care about when writing unsafe Rust, so that your unsafe Rust has appropriate safety rails before anybody else touches it.

// Safety: Can't touch this while anybody else might write

This reminds me of the mutex thing. Look at C++ std::mutex. You could implement exactly that in Rust. But, that's not what std::sync::Mutex is at all. Because if you implemented it in Rust, C++ std::mutex is either useless or unsafe and clearly we'd prefer neither.

But do you have some examples of Rust shared memory IPC that you believe are unsafe? It might be instructive to either show why they're actually safe after all or, alternatively, go add the unsafety explanations and work out what a safe wrapper would look like.

Re: Why asynchronous Rust doesn't work

#218

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

I think you can implement fibers and continuations in WASM by converting the whole program into a giant switch statement and heap allocating frames. There are a few scheme-to-C compilers that do that I think.

Mind, it is not going to be fast as it is going to be hard to generate efficient code ...

Re: Why asynchronous Rust doesn't work

#219

Earlier quoted context omitted.

Honestly, as a consumer of libraries, I much prefer when they're written in Rust (without gratuitous use of `unsafe`) compared to a language which doesn't make you think about these sorts of things as hard.

For me, writing a program is mostly writing a bunch of libraries that I then put together. So I am consuming my libraries mostly myself. Therefore, for me it is important that both the library writing and the library using can be done efficiently. I assume that having a Rust library of something is a good thing. The question for me is: How easy and natural and quick is it to express a concept as a library in Rust?

There are roughly two levels to the discussion:

1. Do you like strong type systems? If so, Rust us great! If you really would e itching for some python or JS, it may bother you, even though the Rust type inference really makes it a non-issue.

2. Do you care about allocations? One could be cheeky and rephrase it as "do you care about performance", but caring about allocations is one of the more advanced optimization concerns and GCed languages can have great performance if you dont hit their pathological cases. But the thing about Rust is that you have as much control as possible to avoid allocating. Entire libraries can allocate nothing more than temporary stack variables, with their primary data being lifetime constrained references the user passes in.

2.5 if you dont care about allocations, then does `Rc` bother you? There are very easy escape hatches when you _just don't care_ if that thing is shared and don't want to deal with lifetimes. But Rust _lets you choose_.

To me, its a pleasure to use.

Re: Why asynchronous Rust doesn't work

#220
post #201

Earlier quoted context omitted.

Because as explained on rustnomicon, there are many ways to access data in parallel ways, and the language only prevents a tiny subset of those cases. However almost every time data races and Rust come together in the same sentence it is as if it would prevent all use cases.

But (unless you've got an excerpt that says otherwise) the Rustonomicon is about unsafe Rust. And I was explaining that safe Rust has data race freedom. The Rustonomicon is not warning you about scary hidden problems in safe Rust, it's warning you about scary problems you need to care about when writing unsafe Rust, so that your unsafe Rust has appropriate safety rails before anybody else touches it. // Safety: Can't…

You as a user of a crate deemed safe, that underneath uses shmem, mmap, or a database, written without taking the proper care to prevent other processes to change exactly the same underlying data segment, written in what knows what, are in for a surprise and long debugging sessions.

The crate public API surface is safe after all, and unless the user has experience in distributed systems, the answer won't come right away.

Post reply on HN