Hacker News new | ask | show | jobs
by uluyol 2379 days ago
Except that it isn't necessary nor is it completely honest. Go and Java take different approaches here, but the article focuses on the merits of the Java approach and the downsides of the approach taken by Go.

Example 1. The article talks about compaction and generational collection as being Good Things(TM), but it doesn't talk about the costs associated with them. Looking at the linked Go article, these approaches suffer from high write barrier overhead. For Go, this isn't worthwhile because escape analysis allocates many young objects on the stack (which btw is effectively bump-pointer allocation) so trying to further reduce GC overhead by increasing the overhead of every pointer write is just not worth it. It may, however, be the right trade-off for Java.

Example 2. Java's many tuning parameters means that programmers who care about performance have to choose the right GC and tune it. If better GCs come out or tweaks to the algorithms are made, these configurations have to be updated. In contrast, Go programs gets these benefits for free. The best approach seems to be to offer a small number of high-level knobs, but it's hard to determine what those are, leading to the two (suboptimal) extremes you see with Go and Java.

2 comments

These are common misconceptions.

> Example 1. The article talks about compaction and generational collection as being Good Things(TM), but it doesn't talk about the costs associated with them. Looking at the linked Go article, these approaches suffer from high write barrier overhead.

You need a write barrier no matter what for any sort of incremental or concurrent GC, to maintain the tricolor invariant. Otherwise there is no way for the runtime system to detect a store from a black object to a white object. Typical GCs will fold the write barrier needed for generational GC into the write barrier needed for incremental/concurrent GC, so there is no need for extra overhead if properly implemented.

> For Go, this isn't worthwhile because escape analysis allocates many young objects on the stack (which btw is effectively bump-pointer allocation)

Java HotSpot has done the same thing for a long time! It's just that in HotSpot escape analysis doesn't really help allocation performance, because the generational GC already offers bump allocation in the nursery. Escape analysis in the JVM does open up more optimizations, though, because it serves as the scalar-replacement-of-aggregates transformation.

> so trying to further reduce GC overhead by increasing the overhead of every pointer write is just not worth it.

This is only because of their specific implementation. There is no need for increased overhead.

> If better GCs come out or tweaks to the algorithms are made, these configurations have to be updated. In contrast, Go programs gets these benefits for free.

There is no reason why Java can't do the same by updating defaults. In fact, they often do.

>> If better GCs come out or tweaks to the algorithms are made, these configurations have to be updated. In contrast, Go programs gets these benefits for free.

> There is no reason why Java can't do the same by updating defaults. In fact, they often do.

Correct. The JVM guys always update the default GC to be the nearest to 'one size fits all'. Obviously if you've made a custom GC configuration then you want a level of tuning that Go does not provide.

Yet another person who only skimmed the article and hasn't read Part 1, which explains GC tuning tradeoffs and addresses the two examples you mentioned. Part 1 debunks the dishonest marketing from Google around Go's GC when it was originally released, and discusses the tradeoffs that weren't disclosed.