mirror of https://github.com/golang/go.git
testing: only compute b.N once when passed -count > 1
When running a benchmark multiple times, instead of re-computing the value of b.N each time, use the value found by the first run. For go test -bench=. -benchtime 3s -count 2 p_test.go on the benchmark in the linked issue; before: BenchmarkBenchmark-4 500 10180593 ns/op --- BENCH: BenchmarkBenchmark-4 p_test.go:13: single call took 10.111079ms p_test.go:13: single call took 1.017298685s p_test.go:13: single call took 5.090096124s BenchmarkBenchmark-4 500 10182164 ns/op --- BENCH: BenchmarkBenchmark-4 p_test.go:13: single call took 10.098169ms p_test.go:13: single call took 1.017712905s p_test.go:13: single call took 5.090898517s PASS ok command-line-arguments 12.244s and after: BenchmarkBenchmark-4 500 10177076 ns/op --- BENCH: BenchmarkBenchmark-4 p_test.go:13: single call took 10.091301ms p_test.go:13: single call took 1.016943125s p_test.go:13: single call took 5.088376028s BenchmarkBenchmark-4 500 10171497 ns/op --- BENCH: BenchmarkBenchmark-4 p_test.go:13: single call took 10.140245ms p_test.go:13: single call took 5.085605921s PASS ok command-line-arguments 11.218s Fixes #23423 Change-Id: Ie66a8c5ac43881eb8741e14105db28745b4d56d3 Reviewed-on: https://go-review.googlesource.com/110775 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
3c8545c5f6
commit
05ca34093b
|
|
@ -4911,10 +4911,6 @@ func TestTestRegexps(t *testing.T) {
|
|||
x_test.go:15: LOG: Y running N=2000000000
|
||||
--- BENCH: BenchmarkX/Y
|
||||
x_test.go:15: LOG: Y running N=1
|
||||
x_test.go:15: LOG: Y running N=100
|
||||
x_test.go:15: LOG: Y running N=10000
|
||||
x_test.go:15: LOG: Y running N=1000000
|
||||
x_test.go:15: LOG: Y running N=100000000
|
||||
x_test.go:15: LOG: Y running N=2000000000
|
||||
--- BENCH: BenchmarkX
|
||||
x_test.go:13: LOG: X running N=1
|
||||
|
|
|
|||
|
|
@ -251,27 +251,20 @@ func (b *B) run() {
|
|||
b.context.processBench(b) // Must call doBench.
|
||||
} else {
|
||||
// Running func Benchmark.
|
||||
b.doBench()
|
||||
b.doBench(0)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *B) doBench() BenchmarkResult {
|
||||
go b.launch()
|
||||
func (b *B) doBench(hint int) BenchmarkResult {
|
||||
go b.launch(hint)
|
||||
<-b.signal
|
||||
return b.result
|
||||
}
|
||||
|
||||
// launch launches the benchmark function. It gradually increases the number
|
||||
// of benchmark iterations until the benchmark runs for the requested benchtime.
|
||||
// launch is run by the doBench function as a separate goroutine.
|
||||
// run1 must have been called on b.
|
||||
func (b *B) launch() {
|
||||
// Signal that we're done whether we return normally
|
||||
// or by FailNow's runtime.Goexit.
|
||||
defer func() {
|
||||
b.signal <- true
|
||||
}()
|
||||
|
||||
// autodetectN runs the benchmark function, gradually increasing the
|
||||
// number of iterations until the benchmark runs for the requested
|
||||
// benchtime.
|
||||
func (b *B) autodetectN() {
|
||||
// Run the benchmark for at least the specified amount of time.
|
||||
d := b.benchTime
|
||||
for n := 1; !b.failed && b.duration < d && n < 1e9; {
|
||||
|
|
@ -289,6 +282,26 @@ func (b *B) launch() {
|
|||
n = roundUp(n)
|
||||
b.runN(n)
|
||||
}
|
||||
}
|
||||
|
||||
// launch launches the benchmark function for hintN iterations. If
|
||||
// hintN == 0, it autodetects the number of benchmark iterations based
|
||||
// on the requested benchtime.
|
||||
// launch is run by the doBench function as a separate goroutine.
|
||||
// run1 must have been called on b.
|
||||
func (b *B) launch(hintN int) {
|
||||
// Signal that we're done whether we return normally
|
||||
// or by FailNow's runtime.Goexit.
|
||||
defer func() {
|
||||
b.signal <- true
|
||||
}()
|
||||
|
||||
if hintN == 0 {
|
||||
b.autodetectN()
|
||||
} else {
|
||||
b.runN(hintN)
|
||||
}
|
||||
|
||||
b.result = BenchmarkResult{b.N, b.duration, b.bytes, b.netAllocs, b.netBytes}
|
||||
}
|
||||
|
||||
|
|
@ -426,6 +439,7 @@ func runBenchmarks(importPath string, matchString func(pat, str string) (bool, e
|
|||
// processBench runs bench b for the configured CPU counts and prints the results.
|
||||
func (ctx *benchContext) processBench(b *B) {
|
||||
for i, procs := range cpuList {
|
||||
var nHint int
|
||||
for j := uint(0); j < *count; j++ {
|
||||
runtime.GOMAXPROCS(procs)
|
||||
benchName := benchmarkName(b.name, procs)
|
||||
|
|
@ -444,7 +458,10 @@ func (ctx *benchContext) processBench(b *B) {
|
|||
}
|
||||
b.run1()
|
||||
}
|
||||
r := b.doBench()
|
||||
r := b.doBench(nHint)
|
||||
if j == 0 {
|
||||
nHint = b.N
|
||||
}
|
||||
if b.failed {
|
||||
// The output could be very long here, but probably isn't.
|
||||
// We print it all, regardless, because we don't want to trim the reason
|
||||
|
|
|
|||
Loading…
Reference in New Issue