aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/export_test.go
diff options
context:
space:
mode:
authorMichael Knyszek <mknyszek@google.com>2021-10-01 15:11:51 -0400
committerMichael Knyszek <mknyszek@google.com>2021-10-29 19:51:20 +0000
commit994049a9ad3d4230d0835ce36616a34a466f6718 (patch)
tree7a247688342c3274fbe8d0046edbcd825eb9dd6d /src/runtime/export_test.go
parent5ec139fa78ac6ba3f0f715b6aa9235d36346a4a4 (diff)
downloadgo-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.go78
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
+}