Live data from Hacker News

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

bitbashing.io

381–390 of 624 posts

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

#381

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…

> If I had to do this in C++, I'd be fighting crashes all the time.

Why? I'd take modern C++ over Rust every day of the week.

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

#383

Earlier quoted context omitted.

> With ARC, you know exactly when you will release your last reference and that's when the resource is freed up. It's more like "you notice when it happens". You don't know in advance when the last reference will be released (if you did, there would be no point in using reference counting). > In terms of performance, ARC offers massive benefits because the memory that's being dereferenced is already in the cache. It…

> It's more like "you notice when it happens". You don't know in advance when the last reference will be released A barista knows when a customer will pay for coffee (after they have placed their order). A barista does not know when that customer will walk in through the door. > (if you did, there would be no point in using reference counting). There’s a difference between being able to deduce when the last reference…

> A barista knows when a customer will pay for coffee (after they have placed their order). A barista does not know when that customer will walk in through the door.

Sorry, no chance of deciphering that.

> There’s a difference between being able to deduce when the last reference is dropped (for example, by profiling code) and not being able to tell anything about when something will happen.

> A particular developer may not know when the last reference to an object is dropped, but they can find out.

The developer can figure out when the last reference to the object is dropped in that particular execution of the program, but not in the general sense, not anymore than they can in a GC'd language.

The only instance where they can point to a place in the code and with certainty say "the reference counted object that was created over there is always destroyed at this line" is in cases where reference counting was not needed in the first place.

> With safe Rust, you shouldn’t be able to access memory that has been freed up. So cache misses on memory that has been released is not a problem in a language that prevents use-after-free bugs :)

I'm not sure why you're talking about freed memory.

Say that thread A is looking at a reference-counted object. Thread B looks at the same object, and modifies the object's reference counter as part of doing this (to ensure that the object stays alive). By doing so, thread B has invalidated thread A's cache. Thread A has to spend time reloading its cache line the next time it accesses the object.

This is a performance issue that's inherent to reference counting.

> I’m pretty sure the choice of using Rust was made precisely because GC isn’t a thing (in all places that love and use rust that is)

Wanting to avoid "GC everywhere", yes. But Rust/C++ programs can have parts that would be better served by (tracing) garbage collection, but where they have to make do with reference counting, because garbage collection is not available.

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

#384

Earlier quoted context omitted.

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…

We do not want functions that take floating point arguments, only u32 should be used. And don't get me started on more than one argument!

you can convert a float to a u32.

you cannot convert an function that calls async code into a sync function.

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

#385

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…

Maybe a better example is returning errors, than const.

Either way, all of these changes are really annoying to make. We want less of these annoyances, not more.

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

#386

Earlier quoted context omitted.

As a quite senior Go developer, I'd like to +1 this a ton. You're far more likely to have shocking edge cases unaccounted for when using channels. I consider every usage very, very carefully. Just like every other language, I think the ultimate solution is to build higher-level abstractions for concurrency patterns (e.g. errgroup) and, now that Go has generics, it's the right time to start building them. If you haven…

I still like channels because they may be a net reduction in the number of concurrency primitives in use, which complicates quantification in the paper - their taxonomy is great, though. Channels have some sharp corners.

Reducing the number of concurrency primitives does not imply reduction in complexity. On the contrary in fact, I've seen the messes created by golang in large production systems. Here's a good article: https://www.uber.com/blog/data-race-patterns-in-go/

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

#387

Rust still isn't the language I'm looking for. It's too complex. Something simpler is needed with the benefits of memory safety.

So anything from Python, Perl, PHP, Visual Basic, Java, C#, Go, Ruby, Erlang, OCaml, Scheme, Common Lisp?

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

#388

Earlier quoted context omitted.

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!

> I still don't even understand why stackless coroutines are necessarily self-referential, but I am quite curious!

Because when stackless coroutines run they don’t have access to the stack that existed when they were created. everything that used to be on the stack needs to get packaged up in a struct (this is what `async fn` does). However now everything that used to point to something else on the stack (which rust understands and is fine with) now points to something else within the “impl Future” struct. Hence you have self referential structs.

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

#389

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 know of a crate that does the above out of the box.

One advantage of the second approach is (if your task runtime is bounded) that you can have soft realtime guarantees for high priority stuff even when you are making progress on low priority stuff and running at 100% CPU.

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

#390
post #289
post #282

Earlier quoted context omitted.

I am very aware of the definition of zero-cost. We're talking about the comparison between using an abstraction vs not using an abstraction. When I said "doesn't have a runtime cost", I meant "the abstraction doesn't have a runtime cost compared to not using the abstraction". If you want your computer to do anything useful, then you have to write code, and that code has a runtime cost. That runtime cost is unavoidabl…

The way you used it in your parent comment didn't make it clear that you were using it properly, hence my clarification. I'm honestly still not sure you've got it right, because Rust abstractions, in general, are not zero-cost. Rust has some zero-cost abstractions in the standard library and Rust has made choices, like monomorphization for generics, that make writing zero-cost abstractions easier and more common in t…

I never said that ALL abstractions in Rust are zero-cost, though the vast majority of them are, and you actually have to explicitly go out of your way to use non-zero-cost abstractions.
Post reply on HN