3 ms·
Yes, it has a borrow checker which restricts some valid code and occasionally makes you jump through hoops and write in a different style. Also, a garbage coll
by nu11ptr 3y ago
Yes, it has a borrow checker which restricts some valid code and occasionally makes you jump through hoops and write in a different style.
Also, a garbage collector that is state of the art (bump allocation, generational, and compacting) is faster overall typically (throughput-wise, but with less predictable latency) than naïve Rc/Arc all over the place (due to usage of "free list" allocator and counter bumps). That isn't to say blisteringly fast Rust isn't possible to write, and in fact it is pretty easy to write by avoiding Rc/Arc except where necessary and using the stack with the borrow checker, but this entails a writing style that is more "low level" and thus takes a bit more thinking.
- dcuthbertson 3y agoThanks for that explanation! I'm going to have to dive into Rc/Arc [0]. Reference counting built into the standard library is really interesting. Several years ago I wrote a Windows kernel minifilter and reference counting is used a lot by anything that interacts with the filter manager. RC was very helpful to ensure the minifilter didn't leak memory when it was unloaded. [0]: https://doc.rust-lang.org/std/sync/struct.Arc.html https://doc.rust-lang.org/std/sync/struct.Arc.html
- HankB99 3y agoIANAGCE (I am not a GC expert.) I thought there were potential costs to using GS. 1. Interrupting the program to sweep, resulting in unpredictable performance. 2. Possibility that a circularly linked group of variables could be impossible to sweep, resulting in memory leaks. 3. Need to check reference counts (along with bounds checks) that degrade performance. Lack of GC (and bounds checking) are factors that make C/C++ performant and then lead to the kind of bugs that result in programs that don't do what they're supposed to do (and at worst, result in security vulnerabilities.) I thought a key goal of Rust was to fix these problems without sacrificing performance.
- nu11ptr 3y ago> 1. Interrupting the program to sweep, resulting in unpredictable performance. See my comment regarding "less predictable latency" (although new advances are making for much more predictable latency - see some of the work done in Java GCs for example) > 2. Possibility that a circularly linked group of variables could be impossible to sweep, resulting in memory leaks. That is not possible in a precise tracing collector, only in reference counting (Rc/Arc) > 3. Need to check reference counts (along with bounds checks) that degrade performance. I think you are referring to reference counting again. Both Rust and C++ have reference counting types as an add on. State of the art tracing collectors don't collect/check dead objects, they compact live ones, and often don't use reference counting directly. Most objects die young. > Lack of GC (and bounds checking) are factors that make C/C++ performant and then lead to the kind of bugs that result in programs that don't do what they're supposed to do (and at worst, result in security vulnerabilities.) Replace "performant" with "predictable performance" > I thought a key goal of Rust was to fix these problems without sacrificing performance. Rust, like C/C++, wants you to be able to predict performance and latency and without the baggage of a runtime. Nothing more than trade offs - neither is better or worse. GCs often do perform better with the trade off of latency predictability, but as always it depends on use case as to what is appropriate. Rust likely made the right choice for its domain.
- kaba0 3y agoWhat kind of GC do you talk about here? (RC is also a GC algorithm, but you seem to mix some of its shortcomings with that of trading GCs). 1) this is generally true, but many part of this can be done concurrently, and if we want to improve latency at the cost of some throughput than there are low-lat GCs that maximize the pause times (it is basically independent from the heap size), so in practice you have similar interrupts as you would from the OS alone. 2) this is not a problem with tracing GCs, only with refcounting (most well known is Python, ObjC and Swift for this perhaps). You can still leak memory everywhere by e.g. storing them in a huge list forever, though, but that is a much rarer and easy to debug bug. 3) this is again only true for RC, and it is the reason why it is slower than tracing GCs, especially when it is multithreaded and the increment/decrement has to be an atomic operation.