Commit 21445b09 authored by Michael Anthony Knyszek's avatar Michael Anthony Knyszek Committed by Michael Knyszek

runtime: make the scavenger self-paced

Currently the runtime background scavenger is paced externally,
controlled by a collection of variables which together describe a line
that we'd like to stay under.

However, the line to stay under is computed as a function of the number
of free and unscavenged huge pages in the heap at the end of the last
GC. Aside from this number being inaccurate (which is still acceptable),
the scavenging system also makes an order-of-magnitude assumption as to
how expensive scavenging a single page actually is.

This change simplifies the scavenger in preparation for making it
operate on bitmaps. It makes it so that the scavenger paces itself, by
measuring the amount of time it takes to scavenge a single page. The
scavenging methods on mheap already avoid breaking huge pages, so if we
scavenge a real huge page, then we'll have paced correctly, otherwise
we'll sleep for longer to avoid using more than scavengePercent wall
clock time.

Unfortunately, all this involves measuring time, which is quite tricky.
Currently we don't directly account for long process sleeps or OS-level
context switches (which is quite difficult to do in general), but we do
account for Go scheduler overhead and variations in it by maintaining an
EWMA of the ratio of time spent scavenging to the time spent sleeping.
This ratio, as well as the sleep time, are bounded in order to deal with
the aforementioned OS-related anomalies.

Updates #35112.

Change-Id: Ieca8b088fdfca2bebb06bcde25ef14a42fd5216b
Reviewed-on: https://go-review.googlesource.com/c/go/+/201763
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarAustin Clements <austin@google.com>
parent 68dce429
This diff is collapsed.
......@@ -89,25 +89,10 @@ type mheap struct {
// TODO(austin): pagesInUse should be a uintptr, but the 386
// compiler can't 8-byte align fields.
// Scavenger pacing parameters
//
// The two basis parameters and the scavenge ratio parallel the proportional
// sweeping implementation, the primary differences being that:
// * Scavenging concerns itself with RSS, estimated as heapRetained()
// * Rather than pacing the scavenger to the GC, it is paced to a
// time-based rate computed in gcPaceScavenger.
//
// scavengeRetainedGoal represents our goal RSS.
//
// All fields must be accessed with lock.
//
// TODO(mknyszek): Consider abstracting the basis fields and the scavenge ratio
// into its own type so that this logic may be shared with proportional sweeping.
scavengeTimeBasis int64
scavengeRetainedBasis uint64
scavengeBytesPerNS float64
scavengeRetainedGoal uint64
scavengeGen uint64 // incremented on each pacing update
// scavengeGoal is the amount of total retained heap memory (measured by
// heapRetained) that the runtime will try to maintain by returning memory
// to the OS.
scavengeGoal uint64
// Page reclaimer state
......@@ -1561,17 +1546,17 @@ func (h *mheap) scavengeLocked(nbytes uintptr) uintptr {
return released
}
// scavengeIfNeededLocked calls scavengeLocked if we're currently above the
// scavenge goal in order to prevent the mutator from out-running the
// the scavenger.
// scavengeIfNeededLocked scavenges memory assuming that size bytes of memory
// will become unscavenged soon. It only scavenges enough to bring heapRetained
// back down to the scavengeGoal.
//
// h must be locked.
func (h *mheap) scavengeIfNeededLocked(size uintptr) {
if r := heapRetained(); r+uint64(size) > h.scavengeRetainedGoal {
if r := heapRetained(); r+uint64(size) > h.scavengeGoal {
todo := uint64(size)
// If we're only going to go a little bit over, just request what
// we actually need done.
if overage := r + uint64(size) - h.scavengeRetainedGoal; overage < todo {
if overage := r + uint64(size) - h.scavengeGoal; overage < todo {
todo = overage
}
h.scavengeLocked(uintptr(todo))
......
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