runtime: use atomic.Float64 for assist ratio

Change-Id: Ie7f09a7c9545ef9dd1860b1e332c4edbcbf8165e
Reviewed-on: https://go-review.googlesource.com/c/go/+/356170
Reviewed-by: Austin Clements <austin@google.com>
Trust: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Michael Anthony Knyszek 2021-09-24 16:06:07 +00:00 committed by Michael Knyszek
parent 3ec8d4b5ed
commit 75b73d68b3
3 changed files with 11 additions and 21 deletions

View File

@ -400,8 +400,8 @@ retry:
// balance positive. When the required amount of work is low, // balance positive. When the required amount of work is low,
// we over-assist to build up credit for future allocations // we over-assist to build up credit for future allocations
// and amortize the cost of assisting. // and amortize the cost of assisting.
assistWorkPerByte := float64frombits(atomic.Load64(&gcController.assistWorkPerByte)) assistWorkPerByte := gcController.assistWorkPerByte.Load()
assistBytesPerWork := float64frombits(atomic.Load64(&gcController.assistBytesPerWork)) assistBytesPerWork := gcController.assistBytesPerWork.Load()
debtBytes := -gp.gcAssistBytes debtBytes := -gp.gcAssistBytes
scanWork := int64(assistWorkPerByte * float64(debtBytes)) scanWork := int64(assistWorkPerByte * float64(debtBytes))
if scanWork < gcOverAssistWork { if scanWork < gcOverAssistWork {
@ -545,7 +545,7 @@ func gcAssistAlloc1(gp *g, scanWork int64) {
// this scan work counts for. The "1+" is a poor man's // this scan work counts for. The "1+" is a poor man's
// round-up, to ensure this adds credit even if // round-up, to ensure this adds credit even if
// assistBytesPerWork is very low. // assistBytesPerWork is very low.
assistBytesPerWork := float64frombits(atomic.Load64(&gcController.assistBytesPerWork)) assistBytesPerWork := gcController.assistBytesPerWork.Load()
gp.gcAssistBytes += 1 + int64(assistBytesPerWork*float64(workDone)) gp.gcAssistBytes += 1 + int64(assistBytesPerWork*float64(workDone))
// If this is the last worker and we ran out of work, // If this is the last worker and we ran out of work,
@ -638,7 +638,7 @@ func gcFlushBgCredit(scanWork int64) {
return return
} }
assistBytesPerWork := float64frombits(atomic.Load64(&gcController.assistBytesPerWork)) assistBytesPerWork := gcController.assistBytesPerWork.Load()
scanBytes := int64(float64(scanWork) * assistBytesPerWork) scanBytes := int64(float64(scanWork) * assistBytesPerWork)
lock(&work.assistQueue.lock) lock(&work.assistQueue.lock)
@ -672,7 +672,7 @@ func gcFlushBgCredit(scanWork int64) {
if scanBytes > 0 { if scanBytes > 0 {
// Convert from scan bytes back to work. // Convert from scan bytes back to work.
assistWorkPerByte := float64frombits(atomic.Load64(&gcController.assistWorkPerByte)) assistWorkPerByte := gcController.assistWorkPerByte.Load()
scanWork = int64(float64(scanBytes) * assistWorkPerByte) scanWork = int64(float64(scanBytes) * assistWorkPerByte)
atomic.Xaddint64(&gcController.bgScanCredit, scanWork) atomic.Xaddint64(&gcController.bgScanCredit, scanWork)
} }

View File

@ -222,24 +222,14 @@ type gcControllerState struct {
// bytes that should be performed by mutator assists. This is // bytes that should be performed by mutator assists. This is
// computed at the beginning of each cycle and updated every // computed at the beginning of each cycle and updated every
// time heapScan is updated. // time heapScan is updated.
// assistWorkPerByte atomic.Float64
// Stored as a uint64, but it's actually a float64. Use
// float64frombits to get the value.
//
// Read and written atomically.
assistWorkPerByte uint64
// assistBytesPerWork is 1/assistWorkPerByte. // assistBytesPerWork is 1/assistWorkPerByte.
// //
// Stored as a uint64, but it's actually a float64. Use
// float64frombits to get the value.
//
// Read and written atomically.
//
// Note that because this is read and written independently // Note that because this is read and written independently
// from assistWorkPerByte users may notice a skew between // from assistWorkPerByte users may notice a skew between
// the two values, and such a state should be safe. // the two values, and such a state should be safe.
assistBytesPerWork uint64 assistBytesPerWork atomic.Float64
// fractionalUtilizationGoal is the fraction of wall clock // fractionalUtilizationGoal is the fraction of wall clock
// time that should be spent in the fractional mark worker on // time that should be spent in the fractional mark worker on
@ -333,7 +323,7 @@ func (c *gcControllerState) startCycle() {
c.revise() c.revise()
if debug.gcpacertrace > 0 { if debug.gcpacertrace > 0 {
assistRatio := float64frombits(atomic.Load64(&c.assistWorkPerByte)) assistRatio := c.assistWorkPerByte.Load()
print("pacer: assist ratio=", assistRatio, print("pacer: assist ratio=", assistRatio,
" (scan ", gcController.heapScan>>20, " MB in ", " (scan ", gcController.heapScan>>20, " MB in ",
work.initialHeapLive>>20, "->", work.initialHeapLive>>20, "->",
@ -439,8 +429,8 @@ func (c *gcControllerState) revise() {
// cycle. // cycle.
assistWorkPerByte := float64(scanWorkRemaining) / float64(heapRemaining) assistWorkPerByte := float64(scanWorkRemaining) / float64(heapRemaining)
assistBytesPerWork := float64(heapRemaining) / float64(scanWorkRemaining) assistBytesPerWork := float64(heapRemaining) / float64(scanWorkRemaining)
atomic.Store64(&c.assistWorkPerByte, float64bits(assistWorkPerByte)) c.assistWorkPerByte.Store(assistWorkPerByte)
atomic.Store64(&c.assistBytesPerWork, float64bits(assistBytesPerWork)) c.assistBytesPerWork.Store(assistBytesPerWork)
} }
// endCycle computes the trigger ratio for the next cycle. // endCycle computes the trigger ratio for the next cycle.

View File

@ -3646,7 +3646,7 @@ func goexit0(gp *g) {
// Flush assist credit to the global pool. This gives // Flush assist credit to the global pool. This gives
// better information to pacing if the application is // better information to pacing if the application is
// rapidly creating an exiting goroutines. // rapidly creating an exiting goroutines.
assistWorkPerByte := float64frombits(atomic.Load64(&gcController.assistWorkPerByte)) assistWorkPerByte := gcController.assistWorkPerByte.Load()
scanCredit := int64(assistWorkPerByte * float64(gp.gcAssistBytes)) scanCredit := int64(assistWorkPerByte * float64(gp.gcAssistBytes))
atomic.Xaddint64(&gcController.bgScanCredit, scanCredit) atomic.Xaddint64(&gcController.bgScanCredit, scanCredit)
gp.gcAssistBytes = 0 gp.gcAssistBytes = 0