Commit ccca9c9c authored by Rhys Hiltner's avatar Rhys Hiltner Committed by Austin Clements

runtime: reduce GC assist extra credit

Mutator goroutines that allocate memory during the concurrent mark
phase are required to spend some time assisting the garbage
collector. The magnitude of this mandatory assistance is proportional
to the goroutine's allocation debt and subject to the assistance
ratio as calculated by the pacer.

When assisting the garbage collector, a mutator goroutine will go
beyond paying off its allocation debt. It will build up extra credit
to amortize the overhead of the assist.

In fast-allocating applications with high assist ratios, building up
this credit can take the affected goroutine's entire time slice.
Reduce the penalty on each goroutine being selected to assist the GC
in two ways, to spread the responsibility more evenly.

First, do a consistent amount of extra scan work without regard for
the pacer's assistance ratio. Second, reduce the magnitude of the
extra scan work so it can be completed within a few hundred
microseconds.

Commentary on gcOverAssistWork is by Austin Clements, originally in
https://golang.org/cl/24704

Updates #14812
Fixes #16432

Change-Id: I436f899e778c20daa314f3e9f0e2a1bbd53b43e1
Reviewed-on: https://go-review.googlesource.com/25155
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarAustin Clements <austin@google.com>
Reviewed-by: default avatarRick Hudson <rlh@golang.org>
Reviewed-by: default avatarChris Broadfoot <cbro@golang.org>
parent c80e0d37
...@@ -741,11 +741,10 @@ const gcCreditSlack = 2000 ...@@ -741,11 +741,10 @@ const gcCreditSlack = 2000
// can accumulate on a P before updating gcController.assistTime. // can accumulate on a P before updating gcController.assistTime.
const gcAssistTimeSlack = 5000 const gcAssistTimeSlack = 5000
// gcOverAssistBytes determines how many extra allocation bytes of // gcOverAssistWork determines how many extra units of scan work a GC
// assist credit a GC assist builds up when an assist happens. This // assist does when an assist happens. This amortizes the cost of an
// amortizes the cost of an assist by pre-paying for this many bytes // assist by pre-paying for this many bytes of future allocations.
// of future allocations. const gcOverAssistWork = 64 << 10
const gcOverAssistBytes = 1 << 20
var work struct { var work struct {
full uint64 // lock-free list of full blocks workbuf full uint64 // lock-free list of full blocks workbuf
......
...@@ -393,10 +393,15 @@ func gcAssistAlloc(gp *g) { ...@@ -393,10 +393,15 @@ func gcAssistAlloc(gp *g) {
} }
// Compute the amount of scan work we need to do to make the // Compute the amount of scan work we need to do to make the
// balance positive. We over-assist to build up credit for // balance positive. When the required amount of work is low,
// future allocations and amortize the cost of assisting. // we over-assist to build up credit for future allocations
debtBytes := -gp.gcAssistBytes + gcOverAssistBytes // and amortize the cost of assisting.
debtBytes := -gp.gcAssistBytes
scanWork := int64(gcController.assistWorkPerByte * float64(debtBytes)) scanWork := int64(gcController.assistWorkPerByte * float64(debtBytes))
if scanWork < gcOverAssistWork {
scanWork = gcOverAssistWork
debtBytes = int64(gcController.assistBytesPerWork * float64(scanWork))
}
retry: retry:
// Steal as much credit as we can from the background GC's // Steal as much credit as we can from the background GC's
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment