]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: measure speed of procyield and osyield
authorRhys Hiltner <rhys.hiltner@gmail.com>
Fri, 26 Jul 2024 17:14:20 +0000 (10:14 -0700)
committerEmmanuel Odeke <emmanuel@orijtech.com>
Thu, 1 Aug 2024 03:06:18 +0000 (03:06 +0000)
These are delay primitives for lock2. If a mutex isn't immediately
available, we can use procyield to tell the processor to wait for a
moment, or osyield to allow the OS to run a different process or thread
if one is waiting. We expect a processor-level yield to be faster than
an os-level yield, and for both of them to be fast relative to entering
a full sleep (via futexsleep or semasleep).

Each architecture has its own way of hinting to the processor that it's
in a spin-wait loop, so procyield presents an architecture-independent
interface for use in lock_futex.go and lock_sema.go.

Measure the (single-threaded) speed of these to confirm.

For #68578

Change-Id: I90cd46ea553f2990395aceb048206285558c877e
Reviewed-on: https://go-review.googlesource.com/c/go/+/601396
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/runtime/export_test.go
src/runtime/runtime_test.go

index 759463755ac5d98c468c16dae163a604ea139e19..b18480d0af26acc1ea2caef6f3622f76874e4c6f 100644 (file)
@@ -1223,6 +1223,9 @@ func PageCachePagesLeaked() (leaked uintptr) {
        return
 }
 
+var ProcYield = procyield
+var OSYield = osyield
+
 type Mutex = mutex
 
 var Lock = lock
index c1bf7f87dbd8253b3ad5b30f7d1df5256b1b1142..0b51dd8c8d15b1ce3c7835c0f022b5d755dfa761 100644 (file)
@@ -539,3 +539,25 @@ func TestTimediv(t *testing.T) {
                })
        }
 }
+
+func BenchmarkProcYield(b *testing.B) {
+       benchN := func(n uint32) func(*testing.B) {
+               return func(b *testing.B) {
+                       for i := 0; i < b.N; i++ {
+                               ProcYield(n)
+                       }
+               }
+       }
+
+       b.Run("1", benchN(1))
+       b.Run("10", benchN(10))
+       b.Run("30", benchN(30)) // active_spin_cnt in lock_sema.go and lock_futex.go
+       b.Run("100", benchN(100))
+       b.Run("1000", benchN(1000))
+}
+
+func BenchmarkOSYield(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               OSYield()
+       }
+}