Skip to content

Commit 6bd56fc

Browse files
aclementsgopherbot
authored andcommitted
testing: improve b.Loop example
The current b.Loop example doesn't focus on the basic usage of b.Loop. Replace this with a new example that uses (slightly) more realistic things to demonstrate the most salient points of b.Loop. We also move the example into an example file so that we can write a real Benchmark function and a real function to be benchmarks, which makes this much closer to what a user would actually write. Updates #61515. Change-Id: I4d830b3bfe3eb3cd8cdecef469fea0541baebb43 Reviewed-on: https://go-review.googlesource.com/c/go/+/635896 Auto-Submit: Austin Clements <[email protected]> Reviewed-by: Junyang Shao <[email protected]> Reviewed-by: Cherry Mui <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 090748d commit 6bd56fc

File tree

2 files changed

+48
-30
lines changed

2 files changed

+48
-30
lines changed

src/testing/benchmark_test.go

-30
Original file line numberDiff line numberDiff line change
@@ -149,36 +149,6 @@ func TestBLoopHasResults(t *testing.T) {
149149
}
150150
}
151151

152-
func ExampleB_Loop() {
153-
simpleFunc := func(i int) int {
154-
return i + 1
155-
}
156-
n := 0
157-
testing.Benchmark(func(b *testing.B) {
158-
// Unlike "for i := range b.N {...}" style loops, this
159-
// setup logic will only be executed once, so simpleFunc
160-
// will always get argument 1.
161-
n++
162-
// It behaves just like "for i := range N {...}", except with keeping
163-
// function call parameters and results alive.
164-
for b.Loop() {
165-
// This function call, if was in a normal loop, will be optimized away
166-
// completely, first by inlining, then by dead code elimination.
167-
// In a b.Loop loop, the compiler ensures that this function is not optimized away.
168-
simpleFunc(n)
169-
}
170-
// This clean-up will only be executed once, so after the benchmark, the user
171-
// will see n == 2.
172-
n++
173-
// Use b.ReportMetric as usual just like what a user may do after
174-
// b.N loop.
175-
})
176-
// We can expect n == 2 here.
177-
178-
// The return value of the above Benchmark could be used just like
179-
// a b.N loop benchmark as well.
180-
}
181-
182152
func ExampleB_RunParallel() {
183153
// Parallel benchmark for text/template.Template.Execute on a single object.
184154
testing.Benchmark(func(b *testing.B) {

src/testing/example_loop_test.go

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package testing_test
6+
7+
import (
8+
"math/rand/v2"
9+
"testing"
10+
)
11+
12+
// ExBenchmark shows how to use b.Loop in a benchmark.
13+
//
14+
// (If this were a real benchmark, not an example, this would be named
15+
// BenchmarkSomething.)
16+
func ExBenchmark(b *testing.B) {
17+
// Generate a large random slice to use as an input.
18+
// Since this is done before the first call to b.Loop(),
19+
// it doesn't count toward the benchmark time.
20+
input := make([]int, 128<<10)
21+
for i := range input {
22+
input[i] = rand.Int()
23+
}
24+
25+
// Perform the benchmark.
26+
for b.Loop() {
27+
// Normally, the compiler would be allowed to optimize away the call
28+
// to sum because it has no side effects and the result isn't used.
29+
// However, inside a b.Loop loop, the compiler ensures function calls
30+
// aren't optimized away.
31+
sum(input)
32+
}
33+
34+
// Outside the loop, the timer is stopped, so we could perform
35+
// cleanup if necessary without affecting the result.
36+
}
37+
38+
func sum(data []int) int {
39+
total := 0
40+
for _, value := range data {
41+
total += value
42+
}
43+
return total
44+
}
45+
46+
func ExampleB_Loop() {
47+
testing.Benchmark(ExBenchmark)
48+
}

0 commit comments

Comments
 (0)