Skip to content

Commit 6600a87

Browse files
committed
testing: implement testing.B.Loop
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 <[email protected]> Reviewed-by: Junyang Shao <[email protected]> Run-TryBot: Junyang Shao <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Pratt <[email protected]>
1 parent c208b91 commit 6600a87

File tree

4 files changed

+31
-0
lines changed

4 files changed

+31
-0
lines changed

api/next/61515.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg testing, method (*B) Loop() bool #61515
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Benchmarks can use the new [B.Loop] method in `for b.Loop() { ... }` loops to determine if iteration should continue.

src/testing/benchmark.go

+13
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ type B struct {
113113
netBytes uint64
114114
// Extra metrics collected by ReportMetric.
115115
extra map[string]float64
116+
// Remaining iterations of Loop() to be executed in benchFunc.
117+
loopN int
116118
}
117119

118120
// StartTimer starts timing a test. This function is called automatically
@@ -187,6 +189,7 @@ func (b *B) runN(n int) {
187189
runtime.GC()
188190
b.resetRaces()
189191
b.N = n
192+
b.loopN = n
190193
b.parallelism = 1
191194
b.ResetTimer()
192195
b.StartTimer()
@@ -349,6 +352,16 @@ func (b *B) ReportMetric(n float64, unit string) {
349352
b.extra[unit] = n
350353
}
351354

355+
// Loop returns true until b.N calls has been made to it.
356+
//
357+
// A benchmark should either use Loop or contain an explicit loop from 0 to b.N, but not both.
358+
// After the benchmark finishes, b.N will contain the total number of calls to op, so the benchmark
359+
// may use b.N to compute other average metrics.
360+
func (b *B) Loop() bool {
361+
b.loopN--
362+
return b.loopN >= 0
363+
}
364+
352365
// BenchmarkResult contains the results of a benchmark run.
353366
type BenchmarkResult struct {
354367
N int // The number of iterations.

src/testing/benchmark_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,22 @@ func TestRunParallelSkipNow(t *testing.T) {
127127
})
128128
}
129129

130+
func TestLoopEqualsRangeOverBN(t *testing.T) {
131+
// Verify that b.N and the b.Loop() iteration count match.
132+
var nIterated, nInfered int
133+
testing.Benchmark(func(b *testing.B) {
134+
i := 0
135+
for b.Loop() {
136+
i++
137+
}
138+
nIterated = i
139+
nInfered = b.N
140+
})
141+
if nIterated != nInfered {
142+
t.Fatalf("Iteration of the two different benchmark loop flavor differs, got %d iterations want %d", nIterated, nInfered)
143+
}
144+
}
145+
130146
func ExampleB_RunParallel() {
131147
// Parallel benchmark for text/template.Template.Execute on a single object.
132148
testing.Benchmark(func(b *testing.B) {

0 commit comments

Comments
 (0)