Live data from Hacker News

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

bitbashing.io

461–470 of 624 posts

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

#461

Earlier quoted context omitted.

> The thing is, these dependencies do exist no matter what language you use Sure, but in a lot of cases, these invariants can be trivially explained, or intuitive enough that it wouldn't even need explanation. While in Rust, you can easily spend a full day just explaining it to the compiler. I remember spending litteral _days_ tweaking intricate lifetimes and scopes just to promise Rust that some variables won't be u…

> Some things I even never managed to be able to express in Rust, even if trivial in C, so I just rely on having a C core library for the hot path, and use it from Rust. i can’t think of anything you can do in c that you can’t do in unsafe rust, and that has the advantage that you can both narrow it down to exactly where you need it and only there, and your can test it in miri to find bugs

> i can’t think of anything you can do in c that you can’t do in unsafe rust

That is not my point.

There is a world between "you can do it" and "you will do it".

Some things in Rust are doable in theory, but end up being so insane to implement that you won't do it in practice. That is my point.

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

#462
post #436

Earlier quoted context omitted.

You can use unsafe if you really want to "turn the borrow-checker off", no?

No, because that doesn't give you automatic memory management, which is the point. When I'm prototyping, there's zero reason for me to care about lifetimes - I just want to allocate an object and let the runtime handle it. When you mark everything in your codebase unsafe (a laborious and unnecessary process that then has to be laboriously undone), you still have to ask the Rust runtime for dynamic memory manually, an…

If you're saying you want GC/Arc then that's more than just "turning off the borrow checker".

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

#463

Earlier quoted context omitted.

You’re seriously suggesting writing a game engine in Python?

You accidentally responded to the wrong comment. I never mentioned a game engine.

This thread is about writing a game engine, so GP didn't "accidentally" respond to the wrong comment. Their question is on-topic.

If your comments aren't relevant to writing a game engine, then they're not relevant to this thread.

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

#464
post #432

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…

> Single ownership with a back reference is a very common need, and it's too hard to do. I've been collecting a list[1] of what memory-management policies programmers actually want in their code; it is far more extensive than any particular language actually implements. Contributions are welcome! I already had back reference on the list, but added some details. When the ownership is indirect (really common) it is dif…

Yes, back-linked objects are probably going to have to be pinned.

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

#465

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…

This is very interesting. How do you manage latency of events coming over the network? Do... you... wind up having to set TCP_NODELAY? •͡˘㇁•͡˘

Embarrassingly, yes, because I can't turn off delayed ACKs from Rust.

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

#466

Earlier quoted context omitted.

> The thing is, these dependencies do exist no matter what language you use Sure, but in a lot of cases, these invariants can be trivially explained, or intuitive enough that it wouldn't even need explanation. While in Rust, you can easily spend a full day just explaining it to the compiler. I remember spending litteral _days_ tweaking intricate lifetimes and scopes just to promise Rust that some variables won't be u…

> Some things I even never managed to be able to express in Rust, even if trivial in C, so I just rely on having a C core library for the hot path, and use it from Rust. i can’t think of anything you can do in c that you can’t do in unsafe rust, and that has the advantage that you can both narrow it down to exactly where you need it and only there, and your can test it in miri to find bugs

To be fair, unsafe Rust has an entirely new set of idiosyncrasies that you have to learn for your code not to cause UB. Most of them revolve around the many ways in which using references can invalidate raw pointers, and using raw pointers can invalidate references, something that simply doesn't exist in C apart from the rarely-used restrict qualifier.

(In particular, it's very easy to inadvertently trigger the footgun of converting a pointer to a reference, then back to a pointer, so that using the original pointer again can invalidate the new pointer.)

Extremely pointer-heavy code is entirely possible in unsafe Rust, but often it's far more difficult to correctly express what you want compared to C. With that in mind, a tightly-scoped core library in C can make a lot of sense; more lines of unsafe code in either language leave more room for bugs to slip in.

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

#467

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…

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

I wonder if locks may have some thread-local registry, at least in debug builds.

If locks can be numbered or otherwise ordered, it would be easy to enforce a strict order of taking locks and an inverse strict order of releasing them, by looking up in the registry which locks your thread is currently holding. This would prevent deadlocks.

This, of course, would require to have an idea of all the locks you may want to hold, and their relative order (at least partial), as Dijkstra described back in the day. But thinking about locks is ahead of time is a good idea anyway.

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

#468

Earlier quoted context omitted.

> So what I'm saying, you need to put in this work no matter which language you choose This is very false. Managed-memory languages don't require you to even think about lifetimes, let alone write them down. Yes, I understand that this is for efficiency - but claiming that you have to think about lifetimes everywhere is just wrong, and irrelevant when discussing topics (prototyping/design work/scripting) where you do…

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.

While this is correct, it's still much easier to think about lifetimes in managed languages. The huge majority of allocated objects gets garbage-collected after a very short time, when they leave the context (similar to RAII).

Mostly you need to think about large and/or important objects, and avoid cycles, and avoid unneeded references to such objects that would live for too long. Such cases are few.

The silver lining is that if you make a mistake and a large object would have to live slightly longer, you won't have to wrangle with the lifetime checker for that small sliver of lifetime. But if you make a big mistake, nothing will warn you about a memory leak, before the prod monitoring does.

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

#469
post #308

Earlier quoted context omitted.

Trying to solve the problem by frequently invoking signal handlers will also show in your latency distribution! I guess if someone wants to use futures as if they were goroutines then it's not a bug, but this sort of presupposes that an opinionated runtime is already shooting signals at itself. Fundamentally the language gives you a primitive for switching execution between one context and another, and the premise of…

>Trying to solve the problem by frequently invoking signal handlers will also show in your latency distribution! So just like any other kind of scheduling? "Frequently" is also very subjective, and there are tradeoffs between throughput, latency, and especially tail latency. You can improve throughput and minimum latency by never preempting tasks, but it's bad for average, median, and tail latency when longer tasks s…

> So just like any other kind of scheduling?

Yes. Industries that care about latency take some pains to avoid this as well, of course.

> io_uring and epoll have nothing to do with it and can't avoid the problem: the problem is with code that can make progress and doesn't need to poll for anything.

They totally can though? If I write the exact same code that is called out as problematic in the post, my non-preemptive runtime will run a variety of tasks while non-preemptive tokio is claimed to run only one. This is because my `accept` method would either submit an "accept sqe" to io_uring and swap to the runtime or do nothing and swap to the runtime (in the case of a multishot accept). Then the runtime would continue processing all cqes in order received, not *only* the `accept` cqes. The tokio `accept` method and event loop could also avoid starving other tasks if the `accept` method was guaranteed to poll at least some portion of the time and all ready handlers from one poll were guaranteed to be called before polling again.

This sort of design solves the problem for any case of "My task that is performing I/O through my runtime is starving my other tasks." The remaining tasks that can starve other tasks are those that perform I/O by bypassing the runtime and those that spend a long time performing computations with no I/O. The former thing sounds like self-sabotage by the user, but unfortunately the latter thing probably requires the user to spend some effort on designing their program.

> The problem isn't unique to Rust either, and it's going to exist in any cooperative multitasking system: if you rely on tasks to yield by themselves, some won't.

If we leave the obvious defects in our software, we will continue running software with obvious defects in it, yes.

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

#470

Earlier quoted context omitted.

> It seems you can’t iterate fast at all in Rust because the code wouldn’t compile Yup, this is correct - and the reason is because Rust forces you to care about efficiency concerns (lifetimes) everywhere . There's no option to "turn the borrow checker off" - which means that when you're in prototyping mode, you pay this huge productivity penalty for no benefit. A language that was designed to be good at iteration wo…

The dev cycle is slower, yes, but once it compiles, there is no debug cycle.

I have found someone that never introduces logic errors, and found out a way to use dependent types in Rust. /s
Post reply on HN