4 ms·
> The difference is that Go relies on escape analysis a lot more than the JVM does, because Go's GC has much slower allocation due to not being generational. T
by ngrilly 9y ago
> The difference is that Go relies on escape analysis a lot more than the JVM does, because Go's GC has much slower allocation due to not being generational.
True, but this is only a part of the story. In Java, every custom type is a reference type. This puts a lot of pressure on the GC because a lot of multiple small objects are created. Go has value types and doesn't suffer from this issue, which is a reason why having a generational GC is not that important for Go.
- littlestymaar 9y ago> This puts a lot of pressure on the GC because a lot of multiple small objects are created. … but they are allocated in the nursery, which isn't comparable to an allocation in Go (by orders of magnitude). It only makes a difference if you have a long-lived object (which must be tenured) and the difference is noticeable only if the object is small enough to be memcopied multiple times at low cost. That's why Go is only significantly faster than Java on the Go's marketing slides and not in real life.
- ngrilly 9y agoI already agreed that allocation is faster in Java than in Go. What I'm saying is that allocation speed is less critical in Go than in Java. In Java, if you allocate an object containing 10 other objects, you have to allocate 11 objects, because you only only have reference types (I know there is ongoing work to introduce value types). This is more work for the allocator, and for the GC. In Go, you allocate only once. Honestly, I'm not sure about this issue being very significant for most programs in either Go or Java. As a reminder, most C, C++ and Rust programs don't use a bump allocator either and they're doing well.
- littlestymaar 9y ago> What I'm saying is that allocation speed is less critical in Go than in Java. Indeed. In fact, Go couldn't afford not to have a generational GC without value type and Java would be really slow with Go's GC. > As a reminder, most C, C++ and Rust programs don't use a bump allocator either and they're doing well. C, C++ and Rust can't use a bump allocator since you need a compacting GC to do so. But allocations are really expensive in these languages and removing them is often the first step of optimization.
- ngrilly 9y ago> Go couldn't afford not to have a generational GC without value type And Java couldn't afford not to have value types without a generational GC ;-) > C, C++ and Rust can't use a bump allocator since you need a compacting GC to do so. But allocations are really expensive in these languages and removing them is often the first step of optimization. Agreed. This is why Go programmers use the same optimizations as C, C++ and Rust programmes is such a case (by allocating from a pool or an arena). Are you aware of cases where what is gained thanks to the bump allocator is lost because of compaction?
- littlestymaar 9y ago> Agreed. This is why Go programmers use the same optimizations as C, C++ and Rust programmes is such a case (by allocating from a pool or an arena). Yes, unfortunately in Go allocations are harder to avoid[1] than in C++ or Rust, because Go rely on escape analysis whereas objects must be manually boxed in the other languages. [1]: https://groups.google.com/forum/#!topic/golang-nuts/Vcgx7hkhd3Q https://groups.google.com/forum/#!topic/golang-nuts/Vcgx7hkh...
- jashmatthews 9y ago> C, C++ and Rust can't use a bump allocator since you need a compacting GC to do so. But allocations are really expensive in these languages and removing them is often the first step of optimization. Not true. You can use exactly the same techniques in C, C++ and Rust. It's called arena based allocation. Even malloc calls can be very cheap. The Hoard allocator uses bump pointer allocation for malloc into empty pages!
- jashmatthews 9y ago> In Java, every custom type is a reference type. I'm not sure this is true in the actual native code produced by the JIT. HotSpot does autobox elimination.
- vitalyd 9y agoNo, it’s sadly true. EA may scalarize the allocation but this optimization falls apart very easily in Hotspot.
- pcwalton 9y ago> Go has value types and doesn't suffer from this issue, which is a reason why having a generational GC is not that important for Go. Go is in the same camp as C#/.NET here, where the generational hypothesis certainly holds and therefore .NET uses a generational garbage collector. I am certain that the generational hypothesis holds for Go as well. Not having a generational GC is a design mistake in Go. Google should fix that.
- ngrilly 9y agoIf you are interested by this topic, here is a relevant discussion on golang-nuts: https://groups.google.com/d/topic/golang-nuts/KJiyv2mV2pU/discussion https://groups.google.com/d/topic/golang-nuts/KJiyv2mV2pU/di... One of the arguments mentioned against having a generational GC is that it would make concurrent GC with low latency harder (because Go permits interior pointers, unlike Java) and slower (because Go only needs write barrier, unlike Java which needs read barrier as far as I know).
- pcwalton 9y agoIan Lance Taylor is wrong in that thread. Interior pointers don't make anything harder: this is a solved problem with card marking. Indeed, .NET has interior pointers, and it doesn't cause any problem at all. Also, I don't believe that the HotSpot GC needs to use read barriers. Read barriers are only necessary if you're concurrently compacting objects (like Azul C4 does). If you have concurrent mark-and-sweep and stop the world only during compaction phases, read barriers are unnecessary.
- vitalyd 9y agoG1 has read barriers for SATB marking. Whether a read barrier is used or not is a function of which GC is used so can’t really say “Hotspot doesn’t use read barriers”.
- pcwalton 9y agoDo you have a reference on G1 read barriers? I believe you, but I can't find any information about that from a Google search. I don't immediately see why you'd need a read barrier for snapshot-at-the-beginning. You only need to trace references from gray objects to white objects that were deleted, which is a write.