mirror of
https://github.com/golang/go
synced 2024-11-17 20:04:47 -07:00
runtime: detangle sweeper pacing from GC pacing
The sweeper's pacing state is global, so detangle it from the GC pacer's state updates so that the GC pacer can be tested. For #44167. Change-Id: Ibcea989cd435b73c5891f777d9f95f9604e03bd1 Reviewed-on: https://go-review.googlesource.com/c/go/+/309273 Trust: Michael Knyszek <mknyszek@google.com> Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
353d5b6c53
commit
413672fc84
@ -971,6 +971,7 @@ func gcMarkTermination(nextTriggerRatio float64) {
|
||||
|
||||
// Update GC trigger and pacing for the next cycle.
|
||||
gcController.commit(nextTriggerRatio)
|
||||
gcPaceSweeper(gcController.trigger)
|
||||
gcPaceScavenger(gcController.heapGoal, gcController.lastHeapGoal)
|
||||
|
||||
// Update timing memstats
|
||||
|
@ -735,40 +735,6 @@ func (c *gcControllerState) commit(triggerRatio float64) {
|
||||
if gcphase != _GCoff {
|
||||
c.revise()
|
||||
}
|
||||
|
||||
// Update sweep pacing.
|
||||
if isSweepDone() {
|
||||
mheap_.sweepPagesPerByte = 0
|
||||
} else {
|
||||
// Concurrent sweep needs to sweep all of the in-use
|
||||
// pages by the time the allocated heap reaches the GC
|
||||
// trigger. Compute the ratio of in-use pages to sweep
|
||||
// per byte allocated, accounting for the fact that
|
||||
// some might already be swept.
|
||||
heapLiveBasis := atomic.Load64(&c.heapLive)
|
||||
heapDistance := int64(trigger) - int64(heapLiveBasis)
|
||||
// Add a little margin so rounding errors and
|
||||
// concurrent sweep are less likely to leave pages
|
||||
// unswept when GC starts.
|
||||
heapDistance -= 1024 * 1024
|
||||
if heapDistance < _PageSize {
|
||||
// Avoid setting the sweep ratio extremely high
|
||||
heapDistance = _PageSize
|
||||
}
|
||||
pagesSwept := mheap_.pagesSwept.Load()
|
||||
pagesInUse := mheap_.pagesInUse.Load()
|
||||
sweepDistancePages := int64(pagesInUse) - int64(pagesSwept)
|
||||
if sweepDistancePages <= 0 {
|
||||
mheap_.sweepPagesPerByte = 0
|
||||
} else {
|
||||
mheap_.sweepPagesPerByte = float64(sweepDistancePages) / float64(heapDistance)
|
||||
mheap_.sweepHeapLiveBasis = heapLiveBasis
|
||||
// Write pagesSweptBasis last, since this
|
||||
// signals concurrent sweeps to recompute
|
||||
// their debt.
|
||||
mheap_.pagesSweptBasis.Store(pagesSwept)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// effectiveGrowthRatio returns the current effective heap growth
|
||||
@ -819,6 +785,7 @@ func setGCPercent(in int32) (out int32) {
|
||||
systemstack(func() {
|
||||
lock(&mheap_.lock)
|
||||
out = gcController.setGCPercent(in)
|
||||
gcPaceSweeper(gcController.trigger)
|
||||
gcPaceScavenger(gcController.heapGoal, gcController.lastHeapGoal)
|
||||
unlock(&mheap_.lock)
|
||||
})
|
||||
|
@ -830,3 +830,46 @@ func clobberfree(x unsafe.Pointer, size uintptr) {
|
||||
*(*uint32)(add(x, i)) = 0xdeadbeef
|
||||
}
|
||||
}
|
||||
|
||||
// gcPaceSweeper updates the sweeper's pacing parameters.
|
||||
//
|
||||
// Must be called whenever the GC's pacing is updated.
|
||||
//
|
||||
// The world must be stopped, or mheap_.lock must be held.
|
||||
func gcPaceSweeper(trigger uint64) {
|
||||
assertWorldStoppedOrLockHeld(&mheap_.lock)
|
||||
|
||||
// Update sweep pacing.
|
||||
if isSweepDone() {
|
||||
mheap_.sweepPagesPerByte = 0
|
||||
} else {
|
||||
// Concurrent sweep needs to sweep all of the in-use
|
||||
// pages by the time the allocated heap reaches the GC
|
||||
// trigger. Compute the ratio of in-use pages to sweep
|
||||
// per byte allocated, accounting for the fact that
|
||||
// some might already be swept.
|
||||
heapLiveBasis := atomic.Load64(&gcController.heapLive)
|
||||
heapDistance := int64(trigger) - int64(heapLiveBasis)
|
||||
// Add a little margin so rounding errors and
|
||||
// concurrent sweep are less likely to leave pages
|
||||
// unswept when GC starts.
|
||||
heapDistance -= 1024 * 1024
|
||||
if heapDistance < _PageSize {
|
||||
// Avoid setting the sweep ratio extremely high
|
||||
heapDistance = _PageSize
|
||||
}
|
||||
pagesSwept := mheap_.pagesSwept.Load()
|
||||
pagesInUse := mheap_.pagesInUse.Load()
|
||||
sweepDistancePages := int64(pagesInUse) - int64(pagesSwept)
|
||||
if sweepDistancePages <= 0 {
|
||||
mheap_.sweepPagesPerByte = 0
|
||||
} else {
|
||||
mheap_.sweepPagesPerByte = float64(sweepDistancePages) / float64(heapDistance)
|
||||
mheap_.sweepHeapLiveBasis = heapLiveBasis
|
||||
// Write pagesSweptBasis last, since this
|
||||
// signals concurrent sweeps to recompute
|
||||
// their debt.
|
||||
mheap_.pagesSweptBasis.Store(pagesSwept)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user