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…
> Async is all wrong when there's considerable compute-bound work, and incompatible with threads running at multiple priorities The priority thing is relatively easy to fix: Either create multiple thread pools, and route your futures to them appropriately. Or, write your own event loop, and have it pull from more than one event queue (each with a different priority). It should be even easier than that, but I don’t kn…
Maybe Rust isn’t a good tool for massively concurrent, userspace software
451–460 of 624 posts
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#452Earlier quoted context omitted.
Lifetimes are still important in managed languages. You just have to track them in your head, which is fallible. The difference is that if you get it wrong in a managed language, you get leaks or stale objects or other logic bugs. In rust you get compile time errors.
> The difference is that if you get it wrong in a managed language, you get leaks or stale objects or other logic bugs. Can you provide concrete examples of this? I've literally never had a bug due to the nature of a memory-managed language.
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#453Earlier quoted context omitted.
So you’re stuck choosing a single CPU or having to write send and sync everywhere. There’s a lot of use cases where you would want a thread-per-core model like Glommio to take advantage of multiple cores while still being able to write code like it’s a single thread. > I have used Rust async extensively, and it works great. I consider Rust's Future system to be superior to JS Promises. Sure, but it’s a major headache…
> So you’re stuck choosing a single CPU or having to write send and sync everywhere. There’s a lot of use cases where you would want a thread-per-core model like Glommio to take advantage of multiple cores while still being able to write code like it’s a single thread. thread_local! exists, and you can just call spawn_local on each thread. You can even call spawn_local multiple times on the same thread if you want. Y…
It does.
Problem is that there isn't the documentation, examples etc to help navigate the many options.
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#454Earlier quoted context omitted.
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?
Yes, you can do that. You can use `block_on` to convert an async Future into a synchronous blocking call. So it is entirely possible to convert from the async world back into the sync world.
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#455> Used pervasively, Arc gives you the world’s worst garbage collector. Like a GC, the lifetime of objects and the resources they represent (memory, files, sockets) is unknowable. But you take this loss without the wins you’d get from an actual GC! The lifetime of an Arc isn’t unknowable, it’s determined by where and how you hold it. I think maybe the disconnect in this article is that the author is coming at Rust and…
Reference counting is a type of GC [0]. Just not a very good one in many cases. I think it's a fair assumption to say that the author is aware of what Arcs are and how they work. I believe their point is more so that because of how async works in Rust, users have to reach for Arc over normal RAII far more often than in sync code. So at a certain point, if you have a program where 90% of objects are refcounted, you mi…
…on a server where you can have a ton of RAM. It's superior on client machines because it's friendlier to swapped out memory, which is why Swift doesn't have a GC.
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#456Earlier 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 chose to drop the green thread library so that it could have no runtime, supporting valuable use cases for Rust like embedding a Rust library into a C binary, which we cared about. Go is not really usable for this (technically it's possible, but it's ridiculous for exactly this reason). So those sorts of users are getting a lot of benefit from Rust not having a green threading runtime. As are any users who are n…
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#457Earlier 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…
The point of async/await is that it converts your function into a reentrant state machine (in a different way than compiling a sync function already turned it into a state machine.) The problem with the usual design is that it uses futures, which are bad because they have dynamic lifetimes.
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#458Earlier quoted context omitted.
> A safe async language must guarantee that threads will make progress. You might be looking for parallelism, not concurrency.
No? You don't need parallelism to guarantee global progress as long as the scheduler has the ability to preempt tasks. Of course coroutines (as opposed to e.g. userspace threads) can't really be preempted, which is the issue here.
Preempting tasks is a single-core simulation of parallelism. I suspect there is confusion about what parallelism and concurrency are here: the terms are often used interchangeably (especially saying "concurrency" instead of "parallelism"), but they are definitely not interchangeable - or even, arguably, related at all. Concurrency, by definition, is concerned with continuations. If you remove continuations (async/await and/or futures/promises - depending on the language choices) then you aren't talking about concurrency any more.
Either way, you can use parallelism is Rust today - just use blocking APIs, locking, and threads. I don't get what the big deal is. You can even use concurrency and parallelism together, just use await/async across multiple threads.
I agree with the premise of the article, but the reasoning in this comment chain is something along the lines of "cats are horrible, because 5." The criticism is foreign to the entire subject matter.
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#459Earlier quoted context omitted.
> (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?) To get easier timers, to make cancellation at all possible (how to cancel a sync I/O operation?), and to write composable code. There are patterns that become simpler in async code and much more complicated in sync code.
You cancel a sync IO op similar to how you cancel an async one: have another task (i.e OS thread in this case) issue the cancellation. Select semantically spawns a task per case/variant and does something similar under the hood if cancellation is implemented.
And since the cancellation logic runs on the cancellable thread, you can't really cancel a blocking operation. What you can do is to let it run to completion, check that it was canceled, and discard the value.
Re: Maybe Rust isn’t a good tool for massively concurrent, userspace software
#460OK, 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…
> Rust is race condition free, but not deadlock free. It needs a static deadlock analyzer, one that tracks through the call chain and finds that lock A is locked before lock B on path X, while lock B is locked before path A on path Y. That sounds like a great idea. Something in the style of lockdep, that (when enabled) analyzes what locks are currently held while any other lock is taken, and reports any potential dea…
parking_lot has a deadlock detection feature for when you deadlock that iirc tells you what deadlocked (so you're not trying to figure it out with a debugger and a lot of time) https://amanieu.github.io/parking_lot/parking_lot/deadlock/i...
I also just found out about https://github.com/BurtonQin/lockbud which seems to detect deadlocks and a few other issues statically? (seems to require compiling your crate with the same version of rust as lockbud uses, which from the docs is an old 1.63 nightly build?)