Skip to content

Commit a12cc71

Browse files
committed
testing: make benchmarking faster
The number of estimated iterations required to reach the benchtime is multiplied by a safety margin (to avoid falling just short) and then rounded up to a readable number. With an accurate estimate, in the worse case, the resulting number of iterations could be 3.75x more than necessary: 1.5x for safety * 2.5x to round up (e.g. from 2eX+1 to 5eX). This CL reduces the safety margin to 1.2x. Experimentation showed a diminishing margin of return past 1.2x, although the average case continued to show improvements down to 1.05x. This CL also reduces the maximum round-up multiplier from 2.5x (from 2eX+1 to 5eX) to 2x, by allowing the number of iterations to be of the form 3eX. Both changes improve benchmark wall clock times, and the effects are cumulative. From 1.5x to 1.2x safety margin: package old s new s delta bytes 163 125 -23% encoding/json 27 21 -22% net/http 42 36 -14% runtime 463 418 -10% strings 82 65 -21% Allowing 3eX iterations: package old s new s delta bytes 163 134 -18% encoding/json 27 23 -15% net/http 42 36 -14% runtime 463 422 -9% strings 82 72 -12% Combined: package old s new s delta bytes 163 112 -31% encoding/json 27 20 -26% net/http 42 30 -29% runtime 463 346 -25% strings 82 60 -27% LGTM=crawshaw, r, rsc R=golang-codereviews, crawshaw, r, rsc CC=golang-codereviews https://golang.org/cl/105990045
1 parent 71c9a49 commit a12cc71

File tree

2 files changed

+11
-7
lines changed

2 files changed

+11
-7
lines changed

src/pkg/testing/benchmark.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,16 @@ func roundDown10(n int) int {
157157
return result
158158
}
159159

160-
// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
160+
// roundUp rounds x up to a number of the form [1eX, 2eX, 3eX, 5eX].
161161
func roundUp(n int) int {
162162
base := roundDown10(n)
163163
switch {
164164
case n <= base:
165165
return base
166166
case n <= (2 * base):
167167
return 2 * base
168+
case n <= (3 * base):
169+
return 3 * base
168170
case n <= (5 * base):
169171
return 5 * base
170172
default:
@@ -180,10 +182,10 @@ func (b *B) run() BenchmarkResult {
180182
}
181183

182184
// launch launches the benchmark function. It gradually increases the number
183-
// of benchmark iterations until the benchmark runs for a second in order
184-
// to get a reasonable measurement. It prints timing information in this form
185+
// of benchmark iterations until the benchmark runs for the requested benchtime.
186+
// It prints timing information in this form
185187
// testing.BenchmarkHello 100000 19 ns/op
186-
// launch is run by the fun function as a separate goroutine.
188+
// launch is run by the run function as a separate goroutine.
187189
func (b *B) launch() {
188190
// Run the benchmark for a single iteration in case it's expensive.
189191
n := 1
@@ -199,16 +201,16 @@ func (b *B) launch() {
199201
d := *benchTime
200202
for !b.failed && b.duration < d && n < 1e9 {
201203
last := n
202-
// Predict iterations/sec.
204+
// Predict required iterations.
203205
if b.nsPerOp() == 0 {
204206
n = 1e9
205207
} else {
206208
n = int(d.Nanoseconds() / b.nsPerOp())
207209
}
208-
// Run more iterations than we think we'll need for a second (1.5x).
210+
// Run more iterations than we think we'll need (1.2x).
209211
// Don't grow too fast in case we had timing errors previously.
210212
// Be sure to run at least one more than last time.
211-
n = max(min(n+n/2, 100*last), last+1)
213+
n = max(min(n+n/5, 100*last), last+1)
212214
// Round up to something easy to read.
213215
n = roundUp(n)
214216
b.runN(n)

src/pkg/testing/benchmark_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ var roundUpTests = []struct {
4141
{0, 1},
4242
{1, 1},
4343
{2, 2},
44+
{3, 3},
4445
{5, 5},
4546
{9, 10},
4647
{999, 1000},
4748
{1000, 1000},
4849
{1400, 2000},
4950
{1700, 2000},
51+
{2700, 3000},
5052
{4999, 5000},
5153
{5000, 5000},
5254
{5001, 10000},

0 commit comments

Comments
 (0)