Skip to content

Commit

Permalink
runtime: avoid futile mark worker acquisition
Browse files Browse the repository at this point in the history
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 <[email protected]>
Auto-Submit: Rhys Hiltner <[email protected]>
Reviewed-by: Michael Knyszek <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
rhysh authored and gopherbot committed Aug 1, 2024
1 parent 2caf638 commit e50913c
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/runtime/mgcpacer.go
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,17 @@ func (c *gcControllerState) findRunnableGCWorker(pp *p, now int64) (*g, int64) {
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.
node := (*gcBgMarkWorkerNode)(gcBgMarkWorkerPool.pop())
if node == nil {
Expand Down

0 comments on commit e50913c

Please sign in to comment.