6 ms·
Even that simplification is too much. Java uses a generational GC, so the fewer objects that survive the nursery, the less work it has to do. That benchmark do
by coder543 4y ago
Even that simplification is too much. Java uses a generational GC, so the fewer objects that survive the nursery, the less work it has to do.
That benchmark does not mean Java's GC is faster when you're "actually allocating on the heap". It means Java's GC is faster when you're spewing garbage onto the heap as fast as possible.
Since Go makes heavy use of stack allocation where possible, short-lived garbage usually doesn't end up on the heap, but this benchmark is designed to force that outcome. Go's garbage collector is optimized to minimize latency and STW, but this does come at the cost of decreased throughput. The opposite can be said of the majority of Java GC implementations, which trade latency and STW time for increased throughput.
- vips7L 4y ago> Java uses a generational GC. This depends on implementation. ZGC is not generational yet, but I don’t see how generational or not would invalidate a GC benchmark for the default implementation. > That benchmark does not mean Java's GC is faster when you're "actually allocating on the heap". It actually does at least in the discussion of _default gc implementations_. Just because the default (and only) implementation for Go sacrifices throughput (and relies on the compiler to stack allocate) doesn’t invalidate the benchmark. And honestly if I was in Vegas I’d still bet that ZGC (Java’s non-generational, latency sensitive GC) would beat Go’s implementation here.
- coder543 4y ago> This depends on implementation. ZGC is not generational yet, but I don’t see how generational or not would invalidate a GC benchmark for the default implementation. I never said the benchmark was invalidated, I said that you interpreted the meaning of the benchmark wrong. I like how your reply completely ignored what I said the benchmark meant. That benchmark has a very narrow focus, and generational makes a huge difference for that one benchmark. > And honestly if I was in Vegas I’d still bet that ZGC (Java’s non-generational, latency sensitive GC) would beat Go’s implementation here. I would love to see a holistic set of benchmarks comparing them. Even just that one very narrow benchmark you linked would be fun to see — if ZGC is so good, surely one of the implementations of the benchmark on the website is using ZGC? But I haven’t had time to dig through them. But, part of Go’s charm is that idiomatic code rarely puts tons of pressure on the GC anyways, and a GC can never be faster than stack allocation for a multitude of reasons… which is also why C# has value types.
- jdc 4y agoJava's value types will be ready soon enough: https://openjdk.org/projects/valhalla https://openjdk.org/projects/valhalla
- coder543 4y agoI hope it happens soon! But, if I understood correctly, that design both requires you to explicitly mark a type as a value type when you define it and it doesn’t support inheritance, so I’m skeptical that it will see any real adoption for a long time. Java hasn’t had decades to develop a culture around this feature the way that C# has, and neither are like Go where everything is value typed unless it is one of the built in pointer types, or you explicitly put the value behind a pointer. (The pointers themselves are values, of course, but I think few people are interested in that distinction here.) Go isn’t perfect by a long shot, I just don’t think adding the millionth keyword is going to be a silver bullet for Java’s predisposition towards GC pressure.
- kaba0 4y agoJava’s standard lib has been planned with value types in mind for some time now, plenty of classes will be able to take advantage of them. Also, inheritance is not rampant in Java, at least not in classes that are so numerous that value types would help them. Also, Java is an exceedingly small language, so the millionth keyword comment is unwarranted.
- coder543 4y ago> Also, Java is an exceedingly small language, so the millionth keyword comment is unwarranted. Small compared to what? Java and C++ are extremely competitive in feature bloat, and I can hardly think of anything that is comparable to them. Even C# has a smaller surface area, in my opinion, even though it manages to implement a variety of useful features that Java currently lacks (like async/await and value types), but C# is still a large language — no doubt about it. C# just manages the interactions of its features better than Java, in my opinion, which makes it feel simpler. I have honestly never heard anyone call Java a small language. It is far from that! > Java’s standard lib has been planned with value types in mind for some time now, plenty of classes will be able to take advantage of them. Aren’t the majority of the standard container types using some form of inheritance? That’s what I recall, and that rules them out.
- kaba0 4y ago> That benchmark does not mean Java's GC is faster when you're "actually allocating on the heap" The benchmark doesn’t show it, but it is nonetheless true. Java uses thread local allocation buffers, which is possible due to moving GC, and it is literally as fast as it gets (a single, non-atomic pointer bump)
- coder543 4y agoAgain, GCs just aren’t that simple. You seem to be taking a very literal interpretation of what was said, but that person was implying that Go is only fast when you’re avoiding the heap. They weren’t talking about the actual, literal speed of allocation. My interpretation of their comment is confirmed in their later reply to me, as far as I can tell. Java’s GC design requires more barriers which hinder performance throughout the lifetime of a heap allocation, not just at the time the value was allocated. Either way, Go also uses per-thread caches in its allocator to avoid contention between threads. I don’t believe it is a bump allocator, but this goes back to other tradeoffs being discussed. The number of barriers, the duration of STW, etc. I don’t understand why so many people in here feel the need to declare the superiority of Java GC. Java’s garbage collectors are better for Java, due to the way that Java allocates practically everything on the heap. That doesn’t mean they have zero performance tradeoffs and that they’re perfect. They do have tradeoffs, and not just in complexity of tuning.