]> Cypherpunks.ru repositories - gostls13.git/commitdiff
runtime: create wrappers for gcDrain to identify time in profiles
authorMichael Anthony Knyszek <mknyszek@google.com>
Mon, 21 Aug 2023 22:29:11 +0000 (22:29 +0000)
committerMichael Knyszek <mknyszek@google.com>
Wed, 23 Aug 2023 15:49:39 +0000 (15:49 +0000)
Currently it's impossible to identify in profiles where gcDrain-related
time is coming from. More specifically, what kind of worker. Create
trivial wrappers for each worker so that the difference shows up in
stack traces.

Also, clarify why gcDrain disables write barriers.

Change-Id: I966e3c0b1c583994e691f486bf0ed8cabb91dbbb
Reviewed-on: https://go-review.googlesource.com/c/go/+/521815
Reviewed-by: Austin Clements <austin@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/runtime/mgc.go
src/runtime/mgcmark.go

index 8efee74243e5f1018ad8ce4827fffef48671da64..44ff5fb08b2d854299dc7099f9b30d090637c813 100644 (file)
@@ -1383,7 +1383,7 @@ func gcBgMarkWorker() {
                        default:
                                throw("gcBgMarkWorker: unexpected gcMarkWorkerMode")
                        case gcMarkWorkerDedicatedMode:
-                               gcDrain(&pp.gcw, gcDrainUntilPreempt|gcDrainFlushBgCredit)
+                               gcDrainMarkWorkerDedicated(&pp.gcw, true)
                                if gp.preempt {
                                        // We were preempted. This is
                                        // a useful signal to kick
@@ -1398,11 +1398,11 @@ func gcBgMarkWorker() {
                                }
                                // Go back to draining, this time
                                // without preemption.
-                               gcDrain(&pp.gcw, gcDrainFlushBgCredit)
+                               gcDrainMarkWorkerDedicated(&pp.gcw, false)
                        case gcMarkWorkerFractionalMode:
-                               gcDrain(&pp.gcw, gcDrainFractional|gcDrainUntilPreempt|gcDrainFlushBgCredit)
+                               gcDrainMarkWorkerFractional(&pp.gcw)
                        case gcMarkWorkerIdleMode:
-                               gcDrain(&pp.gcw, gcDrainIdle|gcDrainUntilPreempt|gcDrainFlushBgCredit)
+                               gcDrainMarkWorkerIdle(&pp.gcw)
                        }
                        casgstatus(gp, _Gwaiting, _Grunning)
                })
index 2b4e23823b96edb2fed4bdd07797233778613f72..9ab3b48f2fde30ecc44f1df739a205154ce583bf 100644 (file)
@@ -1011,6 +1011,28 @@ const (
        gcDrainFractional
 )
 
+// gcDrainMarkWorkerIdle is a wrapper for gcDrain that exists to better account
+// mark time in profiles.
+func gcDrainMarkWorkerIdle(gcw *gcWork) {
+       gcDrain(gcw, gcDrainIdle|gcDrainUntilPreempt|gcDrainFlushBgCredit)
+}
+
+// gcDrainMarkWorkerDedicated is a wrapper for gcDrain that exists to better account
+// mark time in profiles.
+func gcDrainMarkWorkerDedicated(gcw *gcWork, untilPreempt bool) {
+       flags := gcDrainFlushBgCredit
+       if untilPreempt {
+               flags |= gcDrainUntilPreempt
+       }
+       gcDrain(gcw, flags)
+}
+
+// gcDrainMarkWorkerFractional is a wrapper for gcDrain that exists to better account
+// mark time in profiles.
+func gcDrainMarkWorkerFractional(gcw *gcWork) {
+       gcDrain(gcw, gcDrainFractional|gcDrainUntilPreempt|gcDrainFlushBgCredit)
+}
+
 // gcDrain scans roots and objects in work buffers, blackening grey
 // objects until it is unable to get more work. It may return before
 // GC is done; it's the caller's responsibility to balance work from
@@ -1032,6 +1054,14 @@ const (
 //
 // gcDrain will always return if there is a pending STW.
 //
+// Disabling write barriers is necessary to ensure that after we've
+// confirmed that we've drained gcw, that we don't accidentally end
+// up flipping that condition by immediately adding work in the form
+// of a write barrier buffer flush.
+//
+// Don't set nowritebarrierrec because it's safe for some callees to
+// have write barriers enabled.
+//
 //go:nowritebarrier
 func gcDrain(gcw *gcWork, flags gcDrainFlags) {
        if !writeBarrier.needed {