launchpad.net/gocheck@v0.0.0-20140225173054-000000000087/benchmark.go (about) 1 // Copyright 2009 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 gocheck 6 7 import ( 8 "fmt" 9 "time" 10 ) 11 12 // testingB is a type passed to Benchmark functions to manage benchmark 13 // timing and to specify the number of iterations to run. 14 type timer struct { 15 start time.Time // Time test or benchmark started 16 duration time.Duration 17 N int 18 bytes int64 19 timerOn bool 20 benchTime time.Duration 21 } 22 23 // StartTimer starts timing a test. This function is called automatically 24 // before a benchmark starts, but it can also used to resume timing after 25 // a call to StopTimer. 26 func (c *C) StartTimer() { 27 if !c.timerOn { 28 c.start = time.Now() 29 c.timerOn = true 30 } 31 } 32 33 // StopTimer stops timing a test. This can be used to pause the timer 34 // while performing complex initialization that you don't 35 // want to measure. 36 func (c *C) StopTimer() { 37 if c.timerOn { 38 c.duration += time.Now().Sub(c.start) 39 c.timerOn = false 40 } 41 } 42 43 // ResetTimer sets the elapsed benchmark time to zero. 44 // It does not affect whether the timer is running. 45 func (c *C) ResetTimer() { 46 if c.timerOn { 47 c.start = time.Now() 48 } 49 c.duration = 0 50 } 51 52 // SetBytes informs the number of bytes that the benchmark processes 53 // on each iteration. If this is called in a benchmark it will also 54 // report MB/s. 55 func (c *C) SetBytes(n int64) { 56 c.bytes = n 57 } 58 59 func (c *C) nsPerOp() int64 { 60 if c.N <= 0 { 61 return 0 62 } 63 return c.duration.Nanoseconds() / int64(c.N) 64 } 65 66 func (c *C) mbPerSec() float64 { 67 if c.bytes <= 0 || c.duration <= 0 || c.N <= 0 { 68 return 0 69 } 70 return (float64(c.bytes) * float64(c.N) / 1e6) / c.duration.Seconds() 71 } 72 73 func (c *C) timerString() string { 74 if c.N <= 0 { 75 return fmt.Sprintf("%3.3fs", float64(c.duration.Nanoseconds())/1e9) 76 } 77 mbs := c.mbPerSec() 78 mb := "" 79 if mbs != 0 { 80 mb = fmt.Sprintf("\t%7.2f MB/s", mbs) 81 } 82 nsop := c.nsPerOp() 83 ns := fmt.Sprintf("%10d ns/op", nsop) 84 if c.N > 0 && nsop < 100 { 85 // The format specifiers here make sure that 86 // the ones digits line up for all three possible formats. 87 if nsop < 10 { 88 ns = fmt.Sprintf("%13.2f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) 89 } else { 90 ns = fmt.Sprintf("%12.1f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) 91 } 92 } 93 return fmt.Sprintf("%8d\t%s%s", c.N, ns, mb) 94 } 95 96 func min(x, y int) int { 97 if x > y { 98 return y 99 } 100 return x 101 } 102 103 func max(x, y int) int { 104 if x < y { 105 return y 106 } 107 return x 108 } 109 110 // roundDown10 rounds a number down to the nearest power of 10. 111 func roundDown10(n int) int { 112 var tens = 0 113 // tens = floor(log_10(n)) 114 for n > 10 { 115 n = n / 10 116 tens++ 117 } 118 // result = 10^tens 119 result := 1 120 for i := 0; i < tens; i++ { 121 result *= 10 122 } 123 return result 124 } 125 126 // roundUp rounds x up to a number of the form [1eX, 2eX, 5eX]. 127 func roundUp(n int) int { 128 base := roundDown10(n) 129 if n < (2 * base) { 130 return 2 * base 131 } 132 if n < (5 * base) { 133 return 5 * base 134 } 135 return 10 * base 136 }