diff options
Diffstat (limited to 'src/testing/benchmark.go')
| -rw-r--r-- | src/testing/benchmark.go | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index 78e1b2de6d..8b84444f38 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -78,7 +78,7 @@ type InternalBenchmark struct { } // B is a type passed to [Benchmark] functions to manage benchmark -// timing and to specify the number of iterations to run. +// timing and control the number of iterations. // // A benchmark ends when its Benchmark function returns or calls any of the methods // FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods must be called @@ -133,8 +133,7 @@ func (b *B) StartTimer() { } // StopTimer stops timing a test. This can be used to pause the timer -// while performing complex initialization that you don't -// want to measure. +// while performing steps that you don't want to measure. func (b *B) StopTimer() { if b.timerOn { b.duration += highPrecisionTimeSince(b.start) @@ -387,7 +386,7 @@ func (b *B) loopSlowPath() bool { b.ResetTimer() return true } - // Handles fixed time case + // Handles fixed iterations case if b.benchTime.n > 0 { if b.N < b.benchTime.n { b.N = b.benchTime.n @@ -396,31 +395,42 @@ func (b *B) loopSlowPath() bool { } return false } - // Handles fixed iteration count case + // Handles fixed time case return b.stopOrScaleBLoop() } -// 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. +// Loop returns true as long as the benchmark should continue running. // -// The parameters and results of function calls inside the body of "for b.Loop() {...}" are guaranteed -// not to be optimized away. -// Also, the local loop scaling for b.Loop ensures the benchmark function containing the loop will only -// be executed once, i.e. for such construct: +// A typical benchmark is structured like: // -// testing.Benchmark(func(b *testing.B) { -// ...(setup) -// for b.Loop() { -// ...(benchmark logic) -// } -// ...(clean-up) +// func Benchmark(b *testing.B) { +// ... setup ... +// for b.Loop() { +// ... code to measure ... +// } +// ... cleanup ... // } // -// The ...(setup) and ...(clean-up) logic will only be executed once. -// Also benchtime=Nx (N>1) will result in exactly N executions instead of N+1 for b.N style loops. +// Loop resets the benchmark timer the first time it is called in a benchmark, +// so any setup performed prior to starting the benchmark loop does not count +// toward the benchmark measurement. +// +// The compiler never optimizes away calls to functions within the body of a +// "for b.Loop() { ... }" loop. This prevents surprises that can otherwise occur +// if the compiler determines that the result of a benchmarked function is +// unused. The loop must be written in exactly this form, and this only applies +// to calls syntactically between the curly braces of the loop. Optimizations +// are performed as usual in any functions called by the loop. +// +// After Loop returns false, b.N contains the total number of iterations that +// ran, so the benchmark may use b.N to compute other average metrics. +// +// Prior to the introduction of Loop, benchmarks were expected to contain an +// explicit loop from 0 to b.N. Benchmarks should either use Loop or contain a +// loop to b.N, but not both. Loop offers more automatic management of the +// benchmark timer, and runs each benchmark function only once per measurement, +// whereas b.N-based benchmarks must run the benchmark function (and any +// associated setup and cleanup) several times. func (b *B) Loop() bool { if b.loopN != 0 && b.loopN < b.N { b.loopN++ |
