Live data from Hacker News

The Garbage Collection Handbook, 2nd Edition

routledge.com

41–50 of 174 posts

Re: The Garbage Collection Handbook, 2nd Edition

#41

if you need code to understand garbage collection, there is walkthrough of garbage collector and C code at http://maplant.com/gc.html is really helpful. I tweaked it to work on amd64 and started adding register scanning based on what eatonphil's discord people told me to do. https://github.com/samsquire/garbage-collector It's not fit for any purpose but more of a learning exercise.

Side topic, but the maplant website design is great.

Re: The Garbage Collection Handbook, 2nd Edition

#42

Earlier quoted context omitted.

Bob Nystrom (of Game Programming Patterns , Crafting Interpreters , and dartfmt fame) also wrote a tutorial implementation[1], of a precise tracing GC as opposed to a conservative one. Regarding register scanning in a conservative GC, Andreas Kling has made (or at least quoted) the amusing observation[2] that your C runtime already has a primitive to dump all callee-save registers to memory: setjmp(). So all you have…

Implementations are unfortunately allowed to do whatever they want to that jmp_buf, they could xor the contents for all you know. Hopefully no implementation does something silly like that.

This seems like a reasonable environmental assumption if you’re already scanning the stack conservatively. I’d be more worried about pointer authentication (AArch64), pointer encryption (Glibc) or perhaps register windows (SPARC, Itanium). Still, as a cheap trick for avoiding assembly it seems to work well enough in non-exotic situations.

Re: The Garbage Collection Handbook, 2nd Edition

#43
post #13

Who would usually need this book?

I’ve written two garbage collectors in my time, neither of which were in a programming language.

One was for an in memory cache of data relationships. Another was to clean up soft references with an RDF graph. Neither were, nor needed to be, particularly sophisticated.

The cache was a compacting collector, the RDF one was mostly a “connectedness” test, pruning those nodes fallen from the graph.

Recall that malloc has a simple garbage collector for its free space, and arguably the level of sophistication that ranks a modern malloc implementation is how it manages its free space.

In the end detritus must be identified and resources reclaimed. So you see how GC like systems can occur in divergent areas of work.

Re: The Garbage Collection Handbook, 2nd Edition

#44

On a related note, I found ART's implementation of Concurrent copying and compaction GC to be pretty novel. Here's a nice write up detailing how handling page faults in userspace come in handy to accomplish that: https://www.tdcommons.org/cgi/viewcontent.cgi?article=4751&c... (pdf) / https://web.archive.org/web/20230216233459/https://www.tdcom... For context, here's a brief overview of the evolution of the Android Ru…

Certainly interesting, but there are no performance numbers mentioned in the white paper comparing userfaultfd to read barriers. So the actual benefit to switching to userfaultfd is unknown (at least in publically accessible documents -- I'm sure Google has done internal performance evaluations).

Using page faults (and/or page protection) to perform compaction instead of barriers is a pretty old technique (see the 1988 paper by Appel, Ellis, and Li [1]; see also the Compressor by Kermany and Petrank [2]). But handling page faults were very expensive (at least on Linux) until the addition of userfaultfd recently.

[1]: https://dl.acm.org/doi/10.1145/960116.53992 [2]: https://dl.acm.org/doi/10.1145/1133255.1134023

Re: The Garbage Collection Handbook, 2nd Edition

#46
post #16

Earlier quoted context omitted.

Rust also uses reference counting, probably the worst sort of garbage collection.

The increment/decrement calls only occur on an explicit call to .clone(). No .clone(), no increment/decrement. You won't see many clones in rust code.

It's how often reference counts are adjusted on hot paths that matters (including in libraries), and back to the original point, reference counting doesn't let you free groups of objects in one go (unlike a tracing GC).

Also it'd be nice if the reference counts were stored separately from the objects. Storing them alongside the object being tracked is a classic mistake made by reference count implementations (it spreads the writes over a large number of cache lines). I was actually surprised that Rust doesn't get this right.

Another issue with manual memory management is that you can't compact the heap.

Re: The Garbage Collection Handbook, 2nd Edition

#47
post #16
post #14

Rust has left the building

Rust also uses reference counting, probably the worst sort of garbage collection.

Only when used in a naïve way, which Rust does not. For example, the increments/decrements are done only when "clone" is called and scope exit respectively, and based on Rust ownership/borrow checking, is rarely done combining the best of both worlds (but yes, implementations with aggressive increment/decrements in loops and on every function call can be very slow). Rust also separates Arc (atomic refs) and Rc (non-atomic refs) and enforces usage scenarios in the type checker giving you cheap Rc in single threaded scenarios. Reference counting when done in a smart way works pretty well, but you obviously have to be a little careful of cycles (which in my experience are pretty rare and fairly obvious when you have such a data type).

Re: The Garbage Collection Handbook, 2nd Edition

#48

I feel the need for garbage collection is a language design mis-feature. That is to say, producing garbage is a language design-mis-feature. To quote Bjarne Stroustrup: > I don't like garbage. I don't like littering. My ideal is to eliminate the > need for a garbage collector by not producing any garbage. That is now > possible. and it's indeed possible. For example It's become pretty much a non-issue in modern C++:…

C++ can actually produce quite a bit of garbage unintentionally, it's why linters will remind you often to call std::move.

That said I much prefer deterministic resource cleanup even in a janky language like C++ over a tracing GC.

Re: The Garbage Collection Handbook, 2nd Edition

#49
post #45

What I really want out of a garbage collector is a "Collect" function with a deadline. Pick a max time it's allowed to run before stopping and returning to the program.

Real time GCs exist such as the IBM Metronome GC. Though I'll be honest and say I haven't heard of many real-time GCs other than the Metronome one. Certainly many new GCs have reduced pause times dramatically but that's orthogonal to real-time GC (as you can make pause times infinitesimally small but not let the mutator actually progress).

Re: The Garbage Collection Handbook, 2nd Edition

#50
post #45

What I really want out of a garbage collector is a "Collect" function with a deadline. Pick a max time it's allowed to run before stopping and returning to the program.

I've achieved GC timing that is good enough for real-time competitive game hosting using .NET6+. Worst case over 4 hours of load testing was an 8ms spike. Average 1-2ms.

The magic trick is to intentionally collect as often as reasonably possible (i.e. at batch/frame/tick processing boundaries) and avoid using sophisticated GC schemes that involve multiple threads or asynchrony.

Oh, and obviously you need to minimize allocations throughout or it won't matter.

Post reply on HN