Live data from Hacker News

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

bitbashing.io

361–370 of 624 posts

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

#361

Yes, async is effectively a much harder version of Rust, and it's regrettable how it's been shoved down the throats of everyone, while only 1% of projects using it really need it. Hover, async is also amazing in these 1% of cases when it's useful. If you have a service that handles massive amounts of network calls at the core (think linkerd, nginx, etc.), or you want to have a massive amount of lightweight tasks in y…

Is there any reason to use async when your platform supports virtual threads? I ask as someone who uses java and is about to rewrite a bunch of code to be able to chuck the entire async paradigm into the trash can and use a blocking model but on virtual threads where blocking is ok.

Hot off the presses from the JVM Language Summit a few weeks ago; The Challenges of Introducing Virtual Threads to the Java Platform [1]

[1] https://www.youtube.com/watch?v=WsCJYQDPrrE

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

#362
post #312

Earlier quoted context omitted.

I don’t see why it would be an either/or. For instance, Rc does not leak memory, and neither do many cases of interior mutability. If an API leaks memory, then I’d like it to be deemed unsafe. That way, leaking a future would be unsafe, so the borrow checker could infer (transitively) that freeing the future means that any references it had are now dead (as it can already infer when a synchronous function call pops r…

> I don’t see why it would be an either/or. For instance, Rc does not leak memory, and neither do many cases of interior mutability. `Rc` and internal mutability together do allow creating cycles and thus leaking with only safe code. I suggest you to read https://cglab.ca/~abeinges/blah/everyone-poops/ if you haven't done already, it explains the historical reasons for why `std::mem::forget` was changed to be safe. >…

What about the other way? There could be a trait that means “references have the same escape semantics as a stack frame”, perhaps called NotLeaky, and then a variant of tokio spawn could require NotLeaky, and return a non-‘static future. NotLeaky could be inferred in the same way as Send and Sync.

As a bonus, high-availability systems could require NotLeaky at the top of their event loop, precluding runtime memory leaks.

Edit: that wouldn’t work, since the future could be leaked by the caller… will read that reference.

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

#363

OK, I suppose I should write to this. As I've mentioned before, I'm writing a high performance metaverse client. Here's a demo video.[1] It's about 40,000 lines of Rust so far. If you are doing a non-crappy metaverse, which is rare, you need to wrangle a rather excessive amount of data in near real time. In games, there's heavy optimization during game development to prevent overloading the play engine. In a metavers…

>It's probably about five people working for a year from being ready.

The trouble is, we actually have tens/hundreds of people, all working on their own. The blessing and curse of open source development

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

#364

Earlier quoted context omitted.

Honestly, the biggest stumbling block for rust and async is the notion of memory pinning. Rust will do a lot of invisible memory relocations under the covers. Which can work great in single threaded contexts. However, once you start talking about threading those invisible memory moves are a hazard. The moment shared memory comes into play everything just gets a whole lot harder with the rust async story. Contrast tha…

Memory pinning in Rust is not a problem that has to do with concurrency because the compiler will never relocate memory when something is referencing it. The problem is however with how stackless coroutines in general (even single-threaded ones, like generators) work. They are inherently self-referential structures, and Rust's memory model likes to pretend such structures don't exist, so you need library workarounds…

>(and the discussion on whether they are actually sound is still open!) Do you have a reference for this? Frankly, maybe I shouldn't ask since I still don't even understand why stackless coroutines are necessarily self-referential, but I am quite curious!

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

#365

I find myself in this weird corner when it comes to async rust. The guy's got a point in that doing a bunch of Arc, RwLock, and general sharing of state is going to get messy. Especially once you are sprinkling 'static all over the place, it infects everything, much like colored functions. I did this whole thing once back when I was starting off where I would Arc stuff, and try to be smart about borrow lifetimes. Tot…

how do you do bidirectional channels/rpc?

like “send request to channel A with message 123, make sure to get a response back from channel B exactly for that message”

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

#366
post #287
post #152

Earlier quoted context omitted.

I think Rust’s async stuff is a little half baked now but I have hope that it will be improved as time goes on. In the mean time it is a little annoying to use, but I don’t mind designing against it by default. I feel less architecturally constrained if more syntactically constrained.

I'm curious what things you consider to be half-baked about Rust async. I've used Rust async extensively for years, and I consider it to be the cleanest and most well designed async system out of any language (and yes, I have used many languages besides Rust).

Async traits come to mind immediately, generally needing more capability to existentially quantify Future types without penalty. Async function types are a mess to write out. More control over heap allocations in async/await futures (we currently have to Box/Pin more often than necessary). Async drop. Better cancellation. Async iteration.

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

#367
I wonder if Rust should have gone down the same path as Java’s Project Loom and implemented async I/O using the same memory model that is used with operating system threads.

I suspect that to take advantage of 1024-thread systems the only sane programming model will be structured concurrency with virtual threads instead of coroutines.

It’s the same progression as we saw in the industry going from unstructured imperative assembly programming to structured programming with modular features.

Both traditional mutexes and to a degree async programming are unstructured and global. They infect the whole codebase and can’t be reasoned about in isolation. This just doesn’t scale.

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

#368

> At this scale, threads won’t cut it—while they’re pretty cheap, fire up a thread per connection and your computer will grind to a halt. Maybe in the 2000's but I feel this reasoning is no longer valid in 2023 and should be put to rest. 10k problem.. Wouldn't modern computing not work if my Linux box couldn't spin up 10k threads? Htop says I'm currently at 4,000 threads on an 8 core machine.

> Maybe in the 2000's but I feel this reasoning is no longer valid in 2023 and should be put to rest.

So do we discard existing ways of making software more efficient because we can be more wasteful on more recent hardware? What if we could develop our software such that 2000s computers are still useful, rather than letting those computers become e-waste?

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

#369

Earlier quoted context omitted.

> because stackfull coroutine requires a runtime that preempts coroutines I've used stackful coroutines many times in many codebases. It never required or used a runtime or preemption. I'm not sure why having a runtime that preempts them would even be useful, since it defeats the reason most people use stackful coroutines in the first place.

> I've used stackful coroutines many times in many codebases. It never required or used a runtime or preemption. Can you tell us which? Go, Haskell and the other usual suspect all have runtime with automatic, transparent preemption.

It was always C++ for some type of high-performance data processing engine. Around half the stackful coroutine implementations were off-the-shelf libraries (e.g. Boost::Context) and the other half were purpose-built from scratch, depending on the feature requirements. The typical model is that you have stackful coroutines at a coarse level, e.g. per database query, which may dispatch hundreds of concurrent state machines. All execution and I/O scheduling is explicitly done by the software, which enables some significant runtime optimizations.

If coroutines can be preempted then it introduces a requirement for concurrency control that otherwise doesn't need to exist and interferes with dynamic cache locality optimizations. These are some of the primary benefits of using stackful coroutines in this context.

Being able to interrupt a stackful coroutine has utility for dealing with an extremely slow or stuck thread but you want this to be zero-overhead unless the thread is actually stuck. In most system designs, the time required to traverse any pair of sequential yield points is well-bounded so things getting "stuck" is usually a bug.

Letting end-users inject arbitrary code into these paths at runtime does require the ability to interrupt the thread but even that is often handled explicitly by more nuanced means than random preemption. Sometimes "extremely slow" is correct and expected behavior, so you have to schedule around it.

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

#370

OK, I suppose I should write to this. As I've mentioned before, I'm writing a high performance metaverse client. Here's a demo video.[1] It's about 40,000 lines of Rust so far. If you are doing a non-crappy metaverse, which is rare, you need to wrangle a rather excessive amount of data in near real time. In games, there's heavy optimization during game development to prevent overloading the play engine. In a metavers…

What’s the server for a metaverse client? Is there a standardized protocol, or a particularly popular one you’re targeting?
Post reply on HN