Live data from Hacker News

Maybe Rust isn’t a good tool for massively concurrent, userspace software

bitbashing.io

91–100 of 624 posts

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#91
post #23
post #3

I love Rust, but async is a hot mess and you cannot just write async code the same way that you write sync code. I'm getting more convinced that mixing the two is a bad idea, and that Go's approach of making everything sync with a single async channel primitive might be right. I'm currently plumbing through some logic to call a sync method on a struct that implements Future and it's... an interesting challenge. While…

I've seen one wasm VM for Rust that offered what looked like transparent M:N, which should solve (in that case) most async difficulties. We'll see how that evolves.

Which one? I wonder what its performance is like.

A good candidate for this is Graal. It can compile (JIT/AOT) both WASM and also LLVM bitcode directly so Rust programs can have full hardware/OS access without WASM limitations, and in theory it could allow apps to fully benefit from the work done on Loom and async. The pieces are all there. The main issue is you need to virtualize IO so that it goes back into the JVM, so the JVM controls all the code on the stack at all times. I think Graal can do this but only in the enterprise edition. Then you'd be able to run ~millions of Rust threads.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#92
post #20
post #16

Earlier quoted context omitted.

Hoare Was Right. (But if you're only firing up a few tasks, why not just use threads? To get a nice wrapper around an I/O event loop?)

Waiting asynchronously on multiple channels/signals. Heterogenous select is really nice.

It really is, but I still favour "unsexy" manual poll/select code with a lot of if/elseing if it means not having to deal with async.

I fully acknowledge that I'm an "old school" system dev who's coming from the C world and not the JS world, so I probably have a certain bias because of that, but I genuinely can't understand how anybody could look at the mess that's Rust's async and think that it was a good design for a language that already had the reputation of being very complicated to write.

I tried to get it, I really did, but my god what a massive mess that is. And it contaminates everything it touches, too. I really love Rust and I do most of my coding in it these days, but every time I encounter async-heavy Rust code my jaw clenches and my vision blurs.

At least my clunky select "runtime" code can be safely contained in a couple functions while the rest of the code remains blissfully unaware of the magic going on under the hood.

Dear people coming from the JS world: give system threads and channels a try. I swear that a lot of the time it's vastly simpler and more elegant. There are very, very few practical problems where async is clearly superior (although plenty where it's arguably superior).

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#93

Anyone know why there isn't a single type/interface that allows for consumers to supply any of Arc, Rc etc boxed values? I haven't investigated it deeply, but I was developing something in Rust, and whether something needs to be threadsafe or not is entirely on the consumer's use case... bad separation of concerns for the provider of a generic interface to have to specify the specific type of boxed value. 100% fine i…

> Anyone know why there isn't a single type/interface that allows for consumers to supply any of Arc, Rc etc boxed values?

Your generic interface just takes a reference to the value inside the box.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#94
post #44
post #32

Earlier quoted context omitted.

Exactly. People are too afraid of using threads these days for some perceived cargo-cult scalability reasons. My rule of thumb is just to use threads if the total number of threads per process won't exceed 1000. (This is assuming you are already switching to communicating using channels or similar abstraction.)

99% of the use cases that ought to use async are server-side web services. If you're not writing one of those, you almost certainly don't need async.

Async for GUIs is also nice. Not essential, but allows you to simply lot of callback code

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#95
post #43
post #20

Earlier quoted context omitted.

Waiting asynchronously on multiple channels/signals. Heterogenous select is really nice.

It's great! But there's nothing about it that requires futures. It really annoys me that something like this isn't built-in: https://github.com/mrkline/channel-drain

That works for channels, but being able to wait other asynchronous things is better. Timeouts for instance.

We could imagine extending this to arbitrary poll-able things. And now we have futures, kind of.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#96

I have been using "async/await is bad, use {feature name[0]}" as a litmus test for people who are generally bad at programming, especially so at concurrent flavour of such. Sure, Rust is certainly verbose and very strict how the ownership rules apply in the context of async, but this is a hard constraint of its memory safety model. We could probably do better while retaining all performance but this is by far one of…

Disliking async/await does not make someone "generally bad at programming". This is a childish ad-hominem mindset that has no place in technical debates. Rust's decision to adopt async/await over green threads was intended to keep the runtime lean, not because it is an inherently better abstraction. Java certainly could have async/await syntactic sugar around its existing futures api, but project loom has greater ambitions by retrofitting asynchronous IO onto the existing thread api. The authors are certainly not "simply wrong" for this decision.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#98

We do not want red and blue functions. Any language that implements async / await as coroutines instead of green threads is making a fundamental CS mistake. https://journal.stuffwithstuff.com/2015/02/01/what-color-is-... Concurrency's correct primitive is Hoare's Communicating Sequential Processes mapped onto green threads. Some languages that have it right are Java (since JDK17 - Java Virtual Threads), Go, Kotlin.

Virtual threading is fun and all until you find out SimpleDateFormat and a bunch of other classes built tight into your standard library aren't thread safe and now you need to go through your program and find out what else you missed. Go too has these fancy green threads at the cost of manually locking resources and finding out about race conditions when you forget about them.

Futures aren't a fundamental CS mistake, they're a design decision. You may disagree with that decision, but the advantage Rust brings is that you don't need to worry about thread safety once your program actually compiles, at the cost of different code styles.

Neither asynchronous processing design is fundamentally wrong, they both have their strengths and weaknesses.

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#99
post #69
post #32

Earlier quoted context omitted.

Exactly. People are too afraid of using threads these days for some perceived cargo-cult scalability reasons. My rule of thumb is just to use threads if the total number of threads per process won't exceed 1000. (This is assuming you are already switching to communicating using channels or similar abstraction.)

The challenge is that async colors functions and many of the popular crates will force you to be async, so it isn't always a choice depending on which crates you need.

Please excuse my ignorance, I haven't done a ton of async Rust programming - but if you're trying to call async Rust from sync Rust, can you not just create a task, have that task push a value through a mpsc channel, shove the task on the executor, and wait for the value to be returned? Is the concern that control over the execution of the task is too coarse grained?

Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software

#100
I've been writing a lot of async lock free rust. The main problem is that tokio futures are 'static, which is because of a design mistake that's baked deep into the rust ecosystem: Leaking memory is 'safe'.

This implies that you can't statically guarantee that a future is cleaned up properly, which means that if you spawn some async work, something may std::mem::forget a future, and then the borrow checker won't know that the references that were transitively handed out by the future are still live.

Rather than sprinkle Arc everywhere, I just use an unsafe crate like this:

https://docs.rs/async-scoped/latest/async_scoped/

This catches 99% of the bugs I would have written in C++, so it's a reasonable compromise. There's been some work to try to implement non-'static futures in a safe way. I'm hoping it succeeds.

The other big problem with rust (but this is on the roadmap to be fixed this year) is that async trait's currently require Box'ed futures, which adds a malloc/free to function call boundaries(!!!)

As for the "just use a channel" advice: I've dealt with large codebases that are structured this way. It explodes your control flow all over the place. I think of channels as the modern equivalent of GOTO. (I do use them, but not often, and certainly not in cases where I just need to run a few things in parallel and then wait for completion.)

Post reply on HN