-
Notifications
You must be signed in to change notification settings - Fork 18.8k
Closed
Labels
Milestone
Description
Writing contention benchmarks involves some boilerplate: https://golang.org/cl/46010043/diff/60001/src/pkg/sync/pool_test.go https://golang.org/cl/49910043/ etc The general form is: const CallsPerSched = 1000 procs := runtime.GOMAXPROCS(-1) N := int32(b.N / CallsPerSched) c := make(chan bool, procs) for p := 0; p < procs; p++ { go func() { var buf bytes.Buffer for atomic.AddInt32(&N, -1) >= 0 { for g := 0; g < CallsPerSched; g++ { f(&buf) } } c <- true }() } for p := 0; p < procs; p++ { <-c } But sometimes: n0 := uintptr(b.N) atomic.AddUintptr(&n, ^uintptr(0)) < n0 { The testing package seems to cap b.N at 2*1e9, but that's not publicly documented as a guarantee. Can/should we say that b.N will always fit in an int32, even if it's of type int? I once even defensively wrote, func BenchmarkPool(b *testing.B) { procs := runtime.GOMAXPROCS(-1) var dec func() bool if unsafe.Sizeof(b.N) == 8 { n := int64(b.N) dec = func() bool { return atomic.AddInt64(&n, -1) >= 0 } } else { n := int32(b.N) dec = func() bool { return atomic.AddInt32(&n, -1) >= 0 } } var p Pool var wg WaitGroup for i := 0; i < procs; i++ { wg.Add(1) go func() { defer wg.Done() for dec() { p.Put(1) p.Get() } }() } wg.Wait() } ... but felt gross about it. We should either document this, or provide a means in the testing package to ease writing benchmarks for contention.
Reactions are currently unavailable