Live data from Hacker News

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

bitbashing.io

171–180 of 624 posts

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

#171

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.

Always with the blooming red and blue functions. You can say exactly the same thing about const. The fact that a function can perform asynchronous operations matters to me and I want it reflected in the type system. I want to design my system on such a way that the asynchronous parts are kept where they belong, and I want the type system's help in doing that. "May perform asynchronous operations" is a property a call…

It would be swell if functions could be generic over this capability at compile time, so that you could get the same guarantees from the type system without implementing the same protocols more than one time.

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

#172
I wish people would stop saying concurrency and parallelism are different.

Concurrency is a subtype of parallelism. All concurrency is parallelism, but leaving some aspects of parallelism off the table.

I've worked in both worlds: I've built codes that manage thousands of connections through the ancient select() call on single processes (classic concurrency- IO multiplexing where most channels are not active simultaneously, and the amount of CPU work per channel is small) to synchronous parallelism on enormous supercomputers using MPI to eke out that last bit from Amdahl's law.

Over time I've come to the conclusion that a thread pool (possibly managed by the language runtime) that uses channels for communication and has optimizations for work stealing (to keep queues balanced) and eliminating context switches. Although it does not reach the optimal throughput of the machine (because shared memory is faster than message passing) it's a straightforward paradigm to work with and the developers of the concurrency/parallel frameworks are wise.

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

#173

Earlier quoted context omitted.

So 99% of projects need raw threads only, according to the author. I doubt that.

It sounds very reasonable to me. I would say 90% of programs don’t need threads or concurrency at all.

Anything that waits on I/O needs concurrency (but not necessarily threads). Web backends, web frontends, deeper backends, desktop GUIs, that's probably 90% of software right there.

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

#174
post #44

Earlier quoted context omitted.

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.

Or desktop programs. Many GUI frameworks have a main thread that updates the layout (among other things) and various background ones.

Async and GUI threads are different concepts. Of course most GUIs have an event loop which can be used as a form of async, but with async you do your calculations in the main thread, while with GUIs you typically spin your calculations off to a different thread.

Most often when doing async you have a small number of tasks repeated many times, then you spin up one thread per CPU, and "randomly" assign each task as it comes in to a thread.

When doing GUI style programming you have a lot of different tasks and each task is done in exactly one thread.

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

#175

Earlier quoted context omitted.

> But then rust also has channels. When you read about it, it talks about "messages", which to me means little objects. Like a few bytes little. This is the solution, pretty much everything I write now is just a few tasks that service some channels. They look at what's arrived and if there's something to output, they will put a message on the appropriate channel for another task to deal with. No sharing objects or an…

Why does Smalltalk constantly get credit for being true OOP? Simula was doing OOP long before Smalltalk. Most languages choose Simula style OOP, and reject the things that make Smalltalk different. If you say Smalltalk is better OOP I might agree, but calling it "true" is not correct.

Alan Kay is generally credited with coming up with the term "object-oriented", so for better or for worse, many people defer to his definition and his embodiment of ideas when looking for a strict definition of the term.

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

#176
post #59

> We want to use the whole computer. Code runs on CPUs, and in 2023, even my phone has eight of the damn things. If I want to use more than 12% of the machine, I need several cores. Isn't that already, in this strong generality, an almost always wrong assumption? Sure, one can do massively parallel or embarrassingly parallel computation. Sure, graphic cards are parallel computers. Sure, OS kernels use multiple cores.…

And there are even different degrees of parallelization. Some things will scale almost linearly to CPU cores, some will share a little state and see diminishing returns, some will share a lot of state and maybe only make good use of 2 cores, and it'll all depend on the hardware too.

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

#177

Earlier quoted context omitted.

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

Sure, it is "childish and ad-hominem", it is also efficient and usually works. Also, non-async/await solutions for concurrency and asynchrony result in a more verbose, complex and bloated syntax, having to invent fancy terms like "structured concurrency" for use cases which in C# are simply expressed by awaiting the task at the point of its consumption and not declaration (no special methods required) or in Rust via…

> Also, non-async/await solutions for concurrency and asynchrony result in a more verbose, complex and bloated syntax

I just write the same code that I would write if it were synchronous and it executes asynchronously.

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

#178
I've used all of the models mentioned. Personally I've found async/await to be the most annoying. However, I think there's an important option that's overlooked here. For many of the domains where these approaches tend to fall down hardest, notably network servers with very many connections (I was cited in the C10K paper on this subject BTW), arenas can absorb a lot of the annoying lifetime issues. They can be per-request, per-connection, per-something else, but however you do it is likely to leave you with a much smaller set of objects and lifetimes that can be managed by other means. Arenas for most things plus a few very well-isolated bits of code to handle the remainder worked for me from at least 1992 through 2017 in code bases up to more than a million lines (yes, highly concurrent the whole way) without having to deal with async/await or promises/futures. Maybe a bit of CSP/actor model here and there, but that's it.

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

#180

Earlier quoted context omitted.

The argument here is that Rust chose to implement coroutines the wrong way. It went the route of stackless coroutines that need async/await and colored functions. This creates all the friction the article laments over. But it also praises Go for its implementation, which is also based on a coroutine of a different kind. Stackful coroutines, which do not have any of these problems. Rust considered using those (and, at…

> Rust considered using those (and, at first, that was the project's direction). Ultimately, they went to the stackless operation model because stackfull coroutine requires a runtime that preempts coroutines (to do essentially what the kernel does with threads). This was deemed too expensive. Stackful coroutines don't require a preemptive runtime. I certainly hope that we didn't end up with colored functions in Rust…

They often implement soft preemption. Tokio and others like Glommio do. Usually, it's based on interrupts. The runtime schedules a timer to fire an interrupt, and some code is injected into the interrupt handler.

This is used to keep track of task runtime quotas so they can yield as soon as possible afterward.

This is the same technique used in Go and many others for preemption. If you don't add this, futures that don't yield can run forever, stalling the system.

You are right that it is not strictly necessary, but in practice, it is so helpful as a guard against the yielding problem that it's ubiquitous.

> I certainly hope that we didn't end up with colored functions in Rust because of such a misconception.

Misconceptions are everywhere unfortunately!

Post reply on HN