diff options
author | Michael Knyszek <mknyszek@google.com> | 2021-10-01 15:11:51 -0400 |
---|---|---|
committer | Michael Knyszek <mknyszek@google.com> | 2021-10-29 19:51:20 +0000 |
commit | 994049a9ad3d4230d0835ce36616a34a466f6718 (patch) | |
tree | 7a247688342c3274fbe8d0046edbcd825eb9dd6d /src/runtime/export_test.go | |
parent | 5ec139fa78ac6ba3f0f715b6aa9235d36346a4a4 (diff) | |
download | go-994049a9ad3d4230d0835ce36616a34a466f6718.tar.gz go-994049a9ad3d4230d0835ce36616a34a466f6718.zip |
runtime: add testing framework and basic tests for GC pacer
This change creates a formal exported interface for the GC pacer and
creates tests for it that simulate some series of GC cycles. The tests
are completely driven by the real pacer implementation, except for
assists, which are idealized (though revise is called repeatedly).
For #44167.
Change-Id: I0112242b07e7702595ca71001d781ad6c1fddd2d
Reviewed-on: https://go-review.googlesource.com/c/go/+/353354
Trust: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/runtime/export_test.go')
-rw-r--r-- | src/runtime/export_test.go | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 01f917bded..2cc89e7121 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1230,3 +1230,81 @@ func GCTestPointerClass(p unsafe.Pointer) string { } const Raceenabled = raceenabled + +const ( + GCBackgroundUtilization = gcBackgroundUtilization + GCGoalUtilization = gcGoalUtilization +) + +type GCController struct { + gcControllerState +} + +func NewGCController(gcPercent int) *GCController { + // Force the controller to escape. We're going to + // do 64-bit atomics on it, and if it gets stack-allocated + // on a 32-bit architecture, it may get allocated unaligned + // space. + g := escape(new(GCController)).(*GCController) + g.init(int32(gcPercent)) + return g +} + +func (c *GCController) StartCycle(stackSize, globalsSize uint64, scannableFrac float64, gomaxprocs int) { + c.scannableStackSize = stackSize + c.globalsScan = globalsSize + c.heapLive = c.trigger + c.heapScan += uint64(float64(c.trigger-c.heapMarked) * scannableFrac) + c.startCycle(0, gomaxprocs) +} + +func (c *GCController) AssistWorkPerByte() float64 { + return c.assistWorkPerByte.Load() +} + +func (c *GCController) HeapGoal() uint64 { + return c.heapGoal +} + +func (c *GCController) HeapLive() uint64 { + return c.heapLive +} + +func (c *GCController) HeapMarked() uint64 { + return c.heapMarked +} + +func (c *GCController) Trigger() uint64 { + return c.trigger +} + +type GCControllerReviseDelta struct { + HeapLive int64 + HeapScan int64 + HeapScanWork int64 + StackScanWork int64 + GlobalsScanWork int64 +} + +func (c *GCController) Revise(d GCControllerReviseDelta) { + c.heapLive += uint64(d.HeapLive) + c.heapScan += uint64(d.HeapScan) + c.scanWork += d.HeapScanWork + d.StackScanWork + d.GlobalsScanWork + c.revise() +} + +func (c *GCController) EndCycle(bytesMarked uint64, assistTime, elapsed int64, gomaxprocs int) { + c.assistTime = assistTime + triggerRatio := c.endCycle(elapsed, gomaxprocs, false) + c.resetLive(bytesMarked) + c.commit(triggerRatio) +} + +var escapeSink interface{} + +//go:noinline +func escape(x interface{}) interface{} { + escapeSink = x + escapeSink = nil + return x +} |