Description
GC Pacer Redesign
Author: Michael Knyszek (with lots of input from Austin Clements, David Chase, and Jeremy Faller)
Abstract
Go's tracing garbage collector runs concurrently with the application, and thus requires an algorithm to determine when to start a new cycle. In the runtime, this algorithm is referred to as the pacer. Until now, the garbage collector has framed this process as an optimization problem, utilizing a proportional controller to achieve a desired stopping-point (that is, the cycle completes just as the heap reaches a certain size) as well as a desired CPU utilization. While this approach has served Go well for a long time, the design has accrued many corner cases due to resolved issues, as well as a backlog of unresolved issues.
I propose redesigning the garbage collector's pacer from the ground up to capture the things it does well and eliminate the problems that have been discovered.
More specifically, I propose:
- Including all non-heap sources of GC work (stacks, globals) in pacing decisions.
- Reframing the pacing problem as a search problem, "solved" by a proportional-integral controller,
- Extending the hard heap goal to the worst-case heap goal of the next GC,
(1) will resolve long-standing issues with small heap sizes, allowing the Go garbage collector to scale down and act more predictably in general.
(2) will eliminate offset error present in the current design, will allow turning off mark-assist almost entirely outside of exceptional cases, improving allocation latency, and will enable clearer designs for setting memory limits on Go applications.
(3) will enable smooth and consistent response to large changes in the live heap size with large GOGC values.
Activity
gopherbot commentedon Feb 8, 2021
Change https://golang.org/cl/290489 mentions this issue:
design: add GC pacer redesign
mknyszek commentedon Feb 8, 2021
By the way: this design feels solid to me, but has not gone through any rounds of feedback yet. In the interest of transparency, I'm hoping to get feedback and work on this here on GitHub going forward.
So, given that, I would not be surprised if there are errors in the document. Please take a look when you have a chance!
CC @randall77 @jeremyfaller @dr2chase @aclements
storozhukBM commentedon Feb 12, 2021
@mknyszek
Do I understand correctly that the forcegcperiod is required because the current pacer does not consider non-heap sources of GC work? Is it necessary to call GC periodically in application with effectively zero heap allocation rate to collects stacks, etc.? If I understood your proposal correctly, it seems like it should be possible to remove these periodic calls of GC, and applications that don't create new goroutines and don't allocate anything on heap should never trigger garbage collections, which is a good benefit by itself.
mknyszek commentedon Feb 13, 2021
@storozhukBM
forcegcperiod
is pretty much completely separate from this proposal. Not accounting for non-heap sources of work more directly affects the minimum heap size and whether the GC reaches its goals. Related though is #44163, which is partly motivated by some of the ill effects of theforcegcperiod
trigger.I believe
forcegcperiod
exists these days to help finalizers run in long-running mostly-idle programs. For example, if you have an external resource tied to the finalizer, you want that cleaned up eventually (and sooner, probably). Going by the API it need not ever run. But, then we could just turn the forced GC on only if there's active finalizers or something, so I'm not convinced that's the only reason. Shrinking stacks periodically also might be a reason, but that seems less critical.Anyway, I have to look into this again so don't quote me. My memory is hazy. :) I'll dig into the reasons why next week (I don't see them documented anywhere).
design: add GC pacer redesign
gopherbot commentedon Feb 16, 2021
Change https://golang.org/cl/292789 mentions this issue:
design: add user-configurable memory target
gopherbot commentedon Feb 18, 2021
Change https://golang.org/cl/293790 mentions this issue:
design: regenerate graphs for GC pacer redesign
design: regenerate graphs for GC pacer redesign
gopherbot commentedon Feb 23, 2021
Change https://golang.org/cl/295509 mentions this issue:
design: add initial conditions section to GC pacer redesign
62 remaining items