Remix.run Logo
pron 8 months ago

1. How significant that portion is may be lower than you think.

2. Stack allocation adds complexity that actually can adversely affect performance. The main problem is that for stack objects to behave more like heap objects, you need to be able to reference them. References into the stack make user-mode threads less flexible. For example, Go takes a significant hit for Go-native interop in goroutines, whereas Java doesn't pay that cost.

3. Why do you, as a user, care if the GC is more complex?

masklinn 8 months ago | parent [-]

> How significant that portion is may be lower than you think.

And it’s probably higher than you think.

> References into the stack make user-mode threads less flexible. For example, Go takes a significant hit for Go-native interop in goroutines, whereas Java doesn't pay that cost.

This has nothing to do with on-stack structure, it has to do with Go not using C-compatible stacks. If this was an actual issue C would take a hit when calling C.

> Why do you, as a user, care if the GC is more complex?

GC complexity impacts its cost and performances. Generational GCs have more overhead than non-generational ones. That cost needs to be reclaimed by avoiding full collections or the generational GC is a net loss.

And that is what the go team observed on many workloads when they experimented with making Go’s GC generational.

pron 8 months ago | parent [-]

> And it’s probably higher than you think.

Possibly, but the question is does it negate the need for a generational GC? Judging by Go's poor GC performance compared to Java -- it doesn't.

> This has nothing to do with on-stack structure, it has to do with Go not using C-compatible stacks

Sure, but any user-mode thread implementation will not be using C-compatible stacks (if it wants to be efficient). Java doesn't use C-compatible stacks yet it doesn't take the hit Go does.

> GC complexity impacts its cost and performances. Generational GCs have more overhead than non-generational ones.

But in this case (ZGC) it doesn't come at a cost.

> And that is what the go team observed on many workloads when they experimented with making Go’s GC generational.

Go's GC is several generations behind the GCs in Java. It is also isn't compacting. Java had such a GC -- CMS, which served the JDK well for many years -- until the next generation (G1) and the next-next generation (ZGC) were developed, at which point it made little sense to keep a non-moving collector.