News for hackers. Stuff that matters.
Re:Reference count, don't garbage collect by arcticbull on Friday July 29, 2022 @06:23PM (#32282435)
RC may turn reads into writes, but of course, GC ends up having to go through literally every piece of memory ever from bottom to top once in a while.

RC limits itself to modifying only relevant objects, whereas GC reads all objects in a super cache-unfriendly way. Yes, an atomic read-modify-write is worse than a read, but it's not worse than a linked-list traversal of all of memory all the time.

And of course, not all kinds of object lend themselves to garbage collection - for instance, file descriptors, since you can't guarantee when or if they'll ever close. So you have to build your own reference counting system on top of your garbage collected system to handle these edge cases.

There's trade-offs, yes, but the trade-off is simply that garbage collected languages refuse to provide the compiler and the runtime all the information they need to know in order to do their jobs - and a massive 30 year long effort kicked off to build a Rube Goldberg machine for closing that knowledge gap.

Re:Reference count, don't garbage collect by klodolph on Friday July 29, 2022 @06:34PM (#32282512)
> RC may turn reads into writes, but of course, GC ends up having to go through literally every piece of memory ever from time to time.

Depends on the GC algorithm used. Various GC algorithms only trace reachable objects, not unreachable ones.

Reference counting does the opposite, more or less. When you deallocate something, it's tracing unreachable objects.

One of the problems with this is that reference counting touches all the memory right before you're done with it.

> And of course, not all kinds of object lend themselves to garbage collection - for instance, file descriptors, since you can't guarantee when or if they'll ever close. So you have to build your own reference counting system on top of your garbage collected system.

This is not a typical solution.

Java threw finalizers into the mix and everyone overused them at first before they realized that finalizers suck. This is bad enough that, in response to "too many files open" in your Java program, you might invoke the GC. Other languages designed since then typically use some kind of scoped system for closing file descriptors. This includes C# and Go.

Garbage collection does not need to be used to collect all objects.

> There's trade-offs, yes, but the trade-off is simply that garbage collected languages refuse to provide the compiler and the runtime all the information they need to know in order to do their jobs - and a massive 30 year long rube goldberg machine was built around closing that gap.

When I hear rhetoric like this, all I think is, "Oh, this person really hates GC, and thinks everyone else should hate GC."

Embedded in this statement are usually some assumptions which should be challenged. For example, "memory should be freed as soon as it is no longer needed".

Re:Reference count, don't garbage collect by arcticbull on Friday July 29, 2022 @06:35PM (#32282517)
> When I hear rhetoric like this, all I think is, "Oh, this person really hates GC, and thinks everyone else should hate GC."

Yeah, I think it's an inelegant, brute-force solution to a language problem - and that we continue to throw good money after bad improving it.

We should be investing in removing the need for GC through smarter compilers and through languages that allow us to better express our intent - and our object graph. Instead, we continue to improve on a giant linked-list traversal through all of live memory to try and infer the object graph at runtime. Without sufficient information to do it efficiently. The fundamental issue is that we don't have languages that express our goals in a way that allows memory management to be elided efficiently.

That doesn't mean I have some particular affinity for reference counting, though. It has its own issues as you rightly point out. I prefer it for its determinism, nothing more.

Re:Reference count, don't garbage collect by klodolph on Friday July 29, 2022 @07:10PM (#32282728)
> Yeah, I think it's an inelegant, brute-force solution to a language problem - and that we continue to throw good money after bad improving it.

Having studied GC, implemented GC, and used it extensively (either as a dev or someone in operations) I'd say that there's just a lot of people out there who don't understand it. That's why people come to the wrong conclusion that it's somehow "inelegant" or "brute-force", when it is definitely neither of those.

There's also a lot of people who formed their opinions on GC from, say, what the JVM was like in the 1990s.

And there's a lot of people who only have a vague idea of how GC works in theory, but no knowledge of deeper theory and no practical knowledge of how real-world GC algorithms work.

Re:Reference count, don't garbage collect by matheusmoreira on Friday July 29, 2022 @11:29PM (#32284032)
> And there's a lot of people who only have a vague idea of how GC works in theory

I agree. To better understand garbage collection, nothing better than implementation. This article is such a joy to read:

https://journal.stuffwithstuff.com/2013/12/08/babys-first-ga...

Re:Reference count, don't garbage collect by ahartmetz on Saturday July 30, 2022 @03:20AM (#32284978)
Even the best "real world" garbage collectors pause the program for order of magnitude a hundred milliseconds, no? I was recently reading some blog posts of the V8 JS engine team.

There is nothing to understand or not understand there, it's hard data.

Re:Reference count, don't garbage collect by pjmlp on Saturday July 30, 2022 @04:22AM (#32285204)
And yet GC haters keep ignoring the hard data about languages like D, Oberon family, Modula-3,Nim, .NET, and plenty others where alongside the tracing GC, there are value types, stack, static global memory, manual memory allocation primitives and unsafe code blocks to perform as much C like coding as performance junkies might feel like doing.
Re:Reference count, don't garbage collect by Tozen on Saturday July 30, 2022 @08:38AM (#32286312)
Good point. Way too many people act like GC means an unremovable curse, versus it can be another option, among various memory management options of a language.
Re:Reference count, don't garbage collect by klodolph on Saturday July 30, 2022 @11:42AM (#32287657)
> Even the best "real world" garbage collectors pause the program for order of magnitude a hundred milliseconds, no?

If you think GC pauses are measured in milliseconds, and not microseconds, then you're reading horribly outdated material. You're off by three orders of magnitude for an off-the-shelf GC with no tuning.

Re:Reference count, don't garbage collect by origin_path on Saturday July 30, 2022 @09:25AM (#32286615)
The best real world garbage collectors are like ZGC, Shenandoah or C4 which don't pause your program at all. They are fully concurrent.

Even if you go for a GC that is designed to balance throughput and latency, like G1, you can still configure what pause times it should target and those can easily be ~10-20msec if you want, with the vast majority of pauses being far less than that (less than 3 msec).

"I was recently reading some blog posts of the V8 JS engine team. There is nothing to understand or not understand there"

Look, if your knowledge of GC comes from reading V8 blog posts then you're proving the grandparent's point pretty nicely. You leaped from an extremely basic and remote understanding of GC to "there's nothing to understand or not understand here".

Re:Reference count, don't garbage collect by ahartmetz on Saturday July 30, 2022 @12:55PM (#32288281)
Serious questions: if these garbage collectors are so good, why aren't they widely used? My guess is that they have downsides such as low throughput, high CPU usage, high memory usage, etc... You can't import a JVM GC into V8, to stay with my example, but you can reimplement the ideas if you have quasi-infinite money like Google.
Re:Reference count, don't garbage collect by origin_path on Saturday July 30, 2022 @06:07PM (#32290834)
For ZGC/Shenandoah because they're new, and they're new because they're extremely hard to implement well. For C4 because it is expensive and requires kernel patches. Also there isn't a whole lot of need for them in many use cases. Web servers for example have far bigger latency problems than GC, normally. Pauseless GC was historically driven by the HFT/finance sector for that reason.

Also yes, pauseless GC tends to have higher overheads than GC that pauses for longer. Whether that matters or not depends a lot on the use cases and actual size of the overheads. For example ZGC is pauseless but not yet generational. Generational ZGC when it launches will improve throughput significantly.

Google haven't done pauseless GC for V8. I don't know why not because they have done one for Android. ART uses a fully concurrent collector iirc. At any rate, although you can't import a JVM GC to V8, you can run JavaScript on the JVM using GraalJS and use the GCs that way. Though I don't recall off hand if Graal supports ZGC yet. There's no deep reason why it couldn't.

Re:Reference count, don't garbage collect by ahartmetz on Sunday July 31, 2022 @06:33AM (#32294640)
Thank you. I didn't know that one GC that I regularly use (as a user) - the one in Android - is so advanced these days. Interesting!
Re:Reference count, don't garbage collect by origin_path on Wednesday August 03, 2022 @06:10AM (#32329759)
ART is a pretty astoundingly advanced JVM which gets nearly no publicity. It's a real shame. I bet a properly supported desktop version would be quite competitive with HotSpot!

https://source.android.com/devices/tech/dalvik/gc-debug#art_...

It also does mixed AOT / JITC, amongst other tricks.

Re:Reference count, don't garbage collect by kaba0 on Friday July 29, 2022 @07:07PM (#32282710)
But reference counting is a GC-algorithm -- that does exactly the same thing: tries to infer the object graph at runtime.

I really don't think it is a language problem, for several algorithms that one may want to write, GC is a necessity as object lifetime is not decidable at compile time. And it's not just some special parallel algorithm, I believe most business problems fall into this category - that's why we have basically "hacks" like RC, shared ptr, etc in low level languages to let us fake a partial GC (not collecting cycles).

On the plus side of GC, it has been one of the biggest productivity boosters the field has seen since the first non-assembly PL.

Re:Reference count, don't garbage collect by eru on Friday July 29, 2022 @10:30PM (#32283788)
I wouldn't call reference counting a hack.

The paper mention elsewhere in the comments, https://web.eecs.umich.edu/~weimerw/2012-4610/reading/bacon-... "A Unifying Theory of Garbage Collection" put this in context.

For example, a generational garbage collection essentially employs a hybrid approach between tracing and reference counting.

Similarly, depending on your system's trade-offs, reference counting might be better. Eg tracing garbage collection works really great for main memory, but for filesystems we typically use reference counting to decide whether to retire an inode. (The paper explains this in more detail.)

Re:Reference count, don't garbage collect by kaba0 on Saturday July 30, 2022 @02:02AM (#32284642)
I meant hack as in languages meant for primarily for manual memory can still have RC (rust, C++), but that will only be a conservative GC algorithm due to no cycle detection. My use of hack here was only to denote that library-only RC , while possible, may not be the best approach and is used as an escape hatch in rare cases.
Re:Reference count, don't garbage collect by eru on Saturday July 30, 2022 @10:28PM (#32292597)
Oh, ok. That makes sense. Though I would count the Boehm Garbage Collector as a hack then, too?

Apropos hacks, have a look at this memory management 'thing' that doesn't move, but manages to compact: https://github.com/plasma-umass/Mesh

Re:Reference count, don't garbage collect by tsimionescu on Saturday July 30, 2022 @02:37AM (#32284824)
> RC limits itself to modifying only relevant objects, whereas GC reads all objects in a super cache-unfriendly way. Yes, an atomic read-modify-write is worse than a read, but it's not worse than a linked-list traversal of all of memory all the time.

All tracing GC algorithms scan only live memory, and they typically do so in an array-like scan (writing some bits in the object header when a pointer to that object is discovered), not in linked-list order.

Re:Reference count, don't garbage collect by bitcharmer on Saturday July 30, 2022 @04:19AM (#32285199)
> RC may turn reads into writes, but of course, GC ends up having to go through literally every piece of memory ever from bottom to top once in a while.

> RC limits itself to modifying only relevant objects, whereas GC reads all objects in a super cache-unfriendly way. Yes, an atomic read-modify-write is worse than a read, but it's not worse than a linked-list traversal of all of memory all the time.

This is patently untrue. Contemporary GCs have had card marking/scanning for 10+ years now.

Re:Reference count, don't garbage collect by garethrowlands on Saturday July 30, 2022 @06:59AM (#32285799)
Pointer chasing is expensive because fetching a random location defeats locality and therefore caches the the CPU's stream detection.

But a compacting GC copies the data it's scanned into a contiguous stream, dramatically improving locality, cache utility and stream detection. And this affects not only subsequent GCs but also the application itself, which may traverse its object graph far more often than the GC does.

Re:Reference count, don't garbage collect by int_19h on Saturday July 30, 2022 @03:00AM (#32284908)
Most GC implementations that I can think of know which bits in memory are pointers and which aren't, and only scan the pointers.