github.com/loov/hrtime@v1.0.3/benchmark.go (about) 1 package hrtime 2 3 import ( 4 "time" 5 ) 6 7 // Benchmark helps benchmarking using time. 8 type Benchmark struct { 9 step int 10 laps []time.Duration 11 start time.Duration 12 stop time.Duration 13 } 14 15 // NewBenchmark creates a new benchmark using time. 16 // Count defines the number of samples to measure. 17 func NewBenchmark(count int) *Benchmark { 18 if count <= 0 { 19 panic("must have count at least 1") 20 } 21 22 return &Benchmark{ 23 step: 0, 24 laps: make([]time.Duration, count), 25 start: 0, 26 stop: 0, 27 } 28 } 29 30 // mustBeCompleted checks whether measurement has been completed. 31 func (bench *Benchmark) mustBeCompleted() { 32 if bench.stop == 0 { 33 panic("benchmarking incomplete") 34 } 35 } 36 37 // finalize calculates diffs for each lap. 38 func (bench *Benchmark) finalize(last time.Duration) { 39 if bench.stop != 0 { 40 return 41 } 42 43 bench.start = bench.laps[0] 44 bench.stop = last 45 for i := range bench.laps[:len(bench.laps)-1] { 46 bench.laps[i] = bench.laps[i+1] - bench.laps[i] 47 } 48 bench.laps[len(bench.laps)-1] = bench.stop - bench.laps[len(bench.laps)-1] 49 } 50 51 // Next starts measuring the next lap. 52 // It will return false, when all measurements have been made. 53 func (bench *Benchmark) Next() bool { 54 now := Now() 55 if bench.step >= len(bench.laps) { 56 bench.finalize(now) 57 return false 58 } 59 bench.laps[bench.step] = Now() 60 bench.step++ 61 return true 62 } 63 64 // Laps returns timing for each lap. 65 func (bench *Benchmark) Laps() []time.Duration { 66 bench.mustBeCompleted() 67 return append(bench.laps[:0:0], bench.laps...) 68 } 69 70 // Name returns name of the benchmark. 71 func (bench *Benchmark) Name() string { return "" } 72 73 // Unit returns units it measures. 74 func (bench *Benchmark) Unit() string { return "ns" } 75 76 // Float64s returns all measurements. 77 func (bench *Benchmark) Float64s() []float64 { 78 measurements := make([]float64, len(bench.laps)) 79 for i := range measurements { 80 measurements[i] = float64(bench.laps[i].Nanoseconds()) 81 } 82 return measurements 83 } 84 85 // Histogram creates an histogram of all the laps. 86 // 87 // It creates binCount bins to distribute the data and uses the 88 // 99.9 percentile as the last bucket range. However, for a nicer output 89 // it might choose a larger value. 90 func (bench *Benchmark) Histogram(binCount int) *Histogram { 91 bench.mustBeCompleted() 92 93 opts := defaultOptions 94 opts.BinCount = binCount 95 96 return NewDurationHistogram(bench.laps, &opts) 97 } 98 99 // HistogramClamp creates an historgram of all the laps clamping minimum and maximum time. 100 // 101 // It creates binCount bins to distribute the data and uses the 102 // maximum as the last bucket. 103 func (bench *Benchmark) HistogramClamp(binCount int, min, max time.Duration) *Histogram { 104 bench.mustBeCompleted() 105 106 laps := make([]time.Duration, 0, len(bench.laps)) 107 for _, lap := range bench.laps { 108 if lap < min { 109 laps = append(laps, min) 110 } else { 111 laps = append(laps, lap) 112 } 113 } 114 115 opts := defaultOptions 116 opts.BinCount = binCount 117 opts.ClampMaximum = float64(max.Nanoseconds()) 118 opts.ClampPercentile = 0 119 120 return NewDurationHistogram(laps, &opts) 121 }