Skip to content

Commit

Permalink
testing: implement testing.B.Loop
Browse files Browse the repository at this point in the history
Initial implementation for testing.B.Loop,
right now the calculation of b.N are still done in the old fasion way,
as of now b.Loop is merely an alias for the old loop over b.N.

For #61515.

Change-Id: If211d0acc5f0c33df530096dceafe0b947ab0c8e
Reviewed-on: https://go-review.googlesource.com/c/go/+/608798
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Run-TryBot: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
  • Loading branch information
JunyangShao committed Sep 20, 2024
1 parent c208b91 commit 6600a87
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 0 deletions.
1 change: 1 addition & 0 deletions api/next/61515.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pkg testing, method (*B) Loop() bool #61515
1 change: 1 addition & 0 deletions doc/next/6-stdlib/99-minor/testing/61515.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Benchmarks can use the new [B.Loop] method in `for b.Loop() { ... }` loops to determine if iteration should continue.
13 changes: 13 additions & 0 deletions src/testing/benchmark.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ type B struct {
netBytes uint64
// Extra metrics collected by ReportMetric.
extra map[string]float64
// Remaining iterations of Loop() to be executed in benchFunc.
loopN int
}

// StartTimer starts timing a test. This function is called automatically
Expand Down Expand Up @@ -187,6 +189,7 @@ func (b *B) runN(n int) {
runtime.GC()
b.resetRaces()
b.N = n
b.loopN = n
b.parallelism = 1
b.ResetTimer()
b.StartTimer()
Expand Down Expand Up @@ -349,6 +352,16 @@ func (b *B) ReportMetric(n float64, unit string) {
b.extra[unit] = n
}

// Loop returns true until b.N calls has been made to it.
//
// A benchmark should either use Loop or contain an explicit loop from 0 to b.N, but not both.
// After the benchmark finishes, b.N will contain the total number of calls to op, so the benchmark
// may use b.N to compute other average metrics.
func (b *B) Loop() bool {
b.loopN--
return b.loopN >= 0
}

// BenchmarkResult contains the results of a benchmark run.
type BenchmarkResult struct {
N int // The number of iterations.
Expand Down
16 changes: 16 additions & 0 deletions src/testing/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@ func TestRunParallelSkipNow(t *testing.T) {
})
}

func TestLoopEqualsRangeOverBN(t *testing.T) {
// Verify that b.N and the b.Loop() iteration count match.
var nIterated, nInfered int
testing.Benchmark(func(b *testing.B) {
i := 0
for b.Loop() {
i++
}
nIterated = i
nInfered = b.N
})
if nIterated != nInfered {
t.Fatalf("Iteration of the two different benchmark loop flavor differs, got %d iterations want %d", nIterated, nInfered)
}
}

func ExampleB_RunParallel() {
// Parallel benchmark for text/template.Template.Execute on a single object.
testing.Benchmark(func(b *testing.B) {
Expand Down

0 comments on commit 6600a87

Please sign in to comment.