mirror of
https://github.com/golang/go
synced 2024-11-23 00:20:12 -07:00
runtime: avoid futile mark worker acquisition
During the GC mark phase, one of the first behaviors of findRunnable is to check if it should execute a GC mark worker. Mark workers often run for many milliseconds in a row, so programs that invoke the scheduler more frequently will see that condition trigger only a tiny fraction of the time. Obtaining a mark worker from the gcBgMarkWorkerPool involves a CAS on a single memory location that's shared across the process. When GOMAXPROCS is large, the resulting contention can waste a significant amount of CPU time. But a sufficiently large GOMAXPROCS also means there's no need for fractional mark workers, making it easier to check ahead of time if we need to run a worker. Check, without committing to a particular worker, whether we would even want to run one. For #68399 Change-Id: I5d8578c2101ee20a8a4156a029584356095ea118 Reviewed-on: https://go-review.googlesource.com/c/go/+/602477 Reviewed-by: Michael Pratt <mpratt@google.com> Auto-Submit: Rhys Hiltner <rhys.hiltner@gmail.com> Reviewed-by: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
2caf638e2f
commit
e50913cefc
@ -752,6 +752,17 @@ func (c *gcControllerState) findRunnableGCWorker(pp *p, now int64) (*g, int64) {
|
|||||||
return nil, now
|
return nil, now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.dedicatedMarkWorkersNeeded.Load() <= 0 && c.fractionalUtilizationGoal == 0 {
|
||||||
|
// No current need for dedicated workers, and no need at all for
|
||||||
|
// fractional workers. Check before trying to acquire a worker; when
|
||||||
|
// GOMAXPROCS is large, that can be expensive and is often unnecessary.
|
||||||
|
//
|
||||||
|
// When a dedicated worker stops running, the gcBgMarkWorker loop notes
|
||||||
|
// the need for the worker before returning it to the pool. If we don't
|
||||||
|
// see the need now, we wouldn't have found it in the pool anyway.
|
||||||
|
return nil, now
|
||||||
|
}
|
||||||
|
|
||||||
// Grab a worker before we commit to running below.
|
// Grab a worker before we commit to running below.
|
||||||
node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
|
node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
|
||||||
if node == nil {
|
if node == nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user