From: Russ Cox Date: Mon, 11 Mar 2024 03:41:33 +0000 (-0400) Subject: time: clean up benchmarks X-Git-Tag: go1.23rc1~902 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=74a0e3160d969fac27a65cd79a76214f6d1abbf5;p=gostls13.git time: clean up benchmarks Comparing BenchmarkStop against very old commits like CL 13094043, I was very confused about how timers had gotten almost 10X slower since 2013. It turns out that CL 68060043 introduced a factor of 1000 in the benchmark cost, by counting batches of 1000 as 1 op instead of 1000 ops, and timers have actually gotten dramatically faster since 2013, with the addition of per-P timer heaps and other optimizations. This CL rewrites the benchmarks to use testing.PB directly, so that the factor of 1000 disappears, and "/op" really means "/op". In the few tests that need to run in batches for one reason or another, add "1000" to the name to make clear that batches are being run. Change-Id: I27ed74d1e420934982e4205aad4f218cdfc42509 Reviewed-on: https://go-review.googlesource.com/c/go/+/570495 Auto-Submit: Russ Cox Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go index 7bad49f413..b50f9cd5a5 100644 --- a/src/time/sleep_test.go +++ b/src/time/sleep_test.go @@ -148,8 +148,7 @@ func TestAfterFuncStarvation(t *testing.T) { wg.Wait() } -func benchmark(b *testing.B, bench func(n int)) { - +func benchmark(b *testing.B, bench func(*testing.PB)) { // Create equal number of garbage timers on each P before starting // the benchmark. var wg sync.WaitGroup @@ -168,11 +167,7 @@ func benchmark(b *testing.B, bench func(n int)) { wg.Wait() b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - bench(1000) - } - }) + b.RunParallel(bench) b.StopTimer() for _, garbage := range garbageAll { @@ -182,27 +177,29 @@ func benchmark(b *testing.B, bench func(n int)) { } } -func BenchmarkAfterFunc(b *testing.B) { - benchmark(b, func(n int) { - c := make(chan bool) - var f func() - f = func() { - n-- - if n >= 0 { - AfterFunc(0, f) - } else { - c <- true +func BenchmarkAfterFunc1000(b *testing.B) { + benchmark(b, func(pb *testing.PB) { + for pb.Next() { + n := 1000 + c := make(chan bool) + var f func() + f = func() { + n-- + if n >= 0 { + AfterFunc(0, f) + } else { + c <- true + } } + AfterFunc(0, f) + <-c } - - AfterFunc(0, f) - <-c }) } func BenchmarkAfter(b *testing.B) { - benchmark(b, func(n int) { - for i := 0; i < n; i++ { + benchmark(b, func(pb *testing.PB) { + for pb.Next() { <-After(1) } }) @@ -210,59 +207,65 @@ func BenchmarkAfter(b *testing.B) { func BenchmarkStop(b *testing.B) { b.Run("impl=chan", func(b *testing.B) { - benchmark(b, func(n int) { - for i := 0; i < n; i++ { + benchmark(b, func(pb *testing.PB) { + for pb.Next() { NewTimer(1 * Second).Stop() } }) }) b.Run("impl=func", func(b *testing.B) { - benchmark(b, func(n int) { - for i := 0; i < n; i++ { + benchmark(b, func(pb *testing.PB) { + for pb.Next() { newTimerFunc(1 * Second).Stop() } }) }) } -func BenchmarkSimultaneousAfterFunc(b *testing.B) { - benchmark(b, func(n int) { - var wg sync.WaitGroup - wg.Add(n) - for i := 0; i < n; i++ { - AfterFunc(0, wg.Done) +func BenchmarkSimultaneousAfterFunc1000(b *testing.B) { + benchmark(b, func(pb *testing.PB) { + for pb.Next() { + n := 1000 + var wg sync.WaitGroup + wg.Add(n) + for range n { + AfterFunc(0, wg.Done) + } + wg.Wait() } - wg.Wait() }) } -func BenchmarkStartStop(b *testing.B) { - benchmark(b, func(n int) { - timers := make([]*Timer, n) - for i := 0; i < n; i++ { - timers[i] = AfterFunc(Hour, nil) - } +func BenchmarkStartStop1000(b *testing.B) { + benchmark(b, func(pb *testing.PB) { + for pb.Next() { + const N = 1000 + timers := make([]*Timer, N) + for i := range timers { + timers[i] = AfterFunc(Hour, nil) + } - for i := 0; i < n; i++ { - timers[i].Stop() + for i := range timers { + timers[i].Stop() + } } }) } func BenchmarkReset(b *testing.B) { b.Run("impl=chan", func(b *testing.B) { - benchmark(b, func(n int) { + benchmark(b, func(pb *testing.PB) { t := NewTimer(Hour) - for i := 0; i < n; i++ { + for pb.Next() { t.Reset(Hour) } t.Stop() }) }) b.Run("impl=func", func(b *testing.B) { - benchmark(b, func(n int) { + benchmark(b, func(pb *testing.PB) { t := newTimerFunc(Hour) - for i := 0; i < n; i++ { + for pb.Next() { t.Reset(Hour) } t.Stop() @@ -270,17 +273,20 @@ func BenchmarkReset(b *testing.B) { }) } -func BenchmarkSleep(b *testing.B) { - benchmark(b, func(n int) { - var wg sync.WaitGroup - wg.Add(n) - for i := 0; i < n; i++ { - go func() { - Sleep(Nanosecond) - wg.Done() - }() +func BenchmarkSleep1000(b *testing.B) { + benchmark(b, func(pb *testing.PB) { + for pb.Next() { + const N = 1000 + var wg sync.WaitGroup + wg.Add(N) + for range N { + go func() { + Sleep(Nanosecond) + wg.Done() + }() + } + wg.Wait() } - wg.Wait() }) } diff --git a/src/time/tick_test.go b/src/time/tick_test.go index a2c6b24861..0ba0c36172 100644 --- a/src/time/tick_test.go +++ b/src/time/tick_test.go @@ -227,9 +227,9 @@ func TestLongAdjustTimers(t *testing.T) { } } func BenchmarkTicker(b *testing.B) { - benchmark(b, func(n int) { + benchmark(b, func(pb *testing.PB) { ticker := NewTicker(Nanosecond) - for i := 0; i < n; i++ { + for pb.Next() { <-ticker.C } ticker.Stop() @@ -237,9 +237,9 @@ func BenchmarkTicker(b *testing.B) { } func BenchmarkTickerReset(b *testing.B) { - benchmark(b, func(n int) { + benchmark(b, func(pb *testing.PB) { ticker := NewTicker(Nanosecond) - for i := 0; i < n; i++ { + for pb.Next() { ticker.Reset(Nanosecond * 2) } ticker.Stop() @@ -247,9 +247,9 @@ func BenchmarkTickerReset(b *testing.B) { } func BenchmarkTickerResetNaive(b *testing.B) { - benchmark(b, func(n int) { + benchmark(b, func(pb *testing.PB) { ticker := NewTicker(Nanosecond) - for i := 0; i < n; i++ { + for pb.Next() { ticker.Stop() ticker = NewTicker(Nanosecond * 2) }