back

by vardump·12y ago·view on hn ↗
GC object graph.

Golang case: 1 object, no child nodes. Nothing to do. Code that does not need to run is the fastest.

JVM case: visit array object and its 100 child nodes. JVM's GC still needs to visit all nodes of the graph. What actually takes time in GC is all those L1/L2/TLB misses and extra page faults caused by following the object graph. If all objects happen to be on a different cache line, L1 spills happen after just 512 references on Intel Sandy Bridge, Ivy Bridge, Haswell, etc. (and sooner in reality). Those extra loads from L2 are not free.

So, in this case Golang needed to visit 1 struct (object). JVM needed to visit 101 objects.

I wasn't talking about object lifetimes at all. I was talking about memory layout and point out in golang you can have the objects sequentially in memory without need for pointer indirection (references).

Thus generational GC doesn't have anything to do with this. Gen GC just something nice to have when a limited call graph generates a lot of temporary objects, i.e. garbage.

1 comments
I mentioned this in the second paragraph. Like I said, I'd be surprised if that helps mark times that much in practice. For minor collections in a generational GC you're typically doing a Cheney scan, so it's very unlikely to matter as you're copying the whole live region of the semispace anyhow. For major collections on tenured objects, in theory it could help, but again I'm skeptical that it will affect mark performance that much, because compaction does an excellent job of mitigating the cache effects. (It's impossible to accurately measure this stuff right now, as the fact that Go's GC is much more immature than the HotSpot GC will skew the numbers.)