Description
In Go 1.19 I tried to switch to using a more correct trigger point in the cons/mark allocation. However, because of how the incorrect trigger point (the precomputed one, gcControllerState.trigger()
, as opposed to the actual one, gcControllerState.heapLive
at the point the GC is triggered) interacts with the PI controller used to smooth the cons/mark measurements, it turns out to generate a worse result overall.
More context may be found here: #53738 (comment).
I think that a smoothing function so sensitive to past history is a bit of a mistake, and this sort of thing could easily happen again. As a result, I propose fixing all of the above in the next release by:
- Switching to a simpler smoothing function, like the moving average of cons/mark measurements over the last 2 cycles, then
- Using the real trigger point as opposed to the precomputed trigger.
In benchmarks, I've observed that the combination of these two:
- Provides a more stable estimate of the actual cons/mark ratio, making the pacer easier to understand,
- Is much more accurate at hitting the heap goal, so the GC respects GOGC much more often and reliably, and,
- Results in a more stable rate of GC assists in the steady-state overall.
Update: It's worth noting that this is all about transient effects in the pacer. In theory if I let the benchmark from #53738 (comment) run much longer this would all wash away, but the transients do also matter, and I think we should switch to something more simple and stable, if less accurate in the long run (the moving average will never find the true steady-state, but I'm starting to think that's OK).