proposal: runtime: GC pacer redesign · Issue #44167 · golang/go (original) (raw)
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.