1package leafnodes 2 3import ( 4 "math" 5 "time" 6 7 "sync" 8 9 "github.com/onsi/ginkgo/types" 10) 11 12type benchmarker struct { 13 mu sync.Mutex 14 measurements map[string]*types.SpecMeasurement 15 orderCounter int 16} 17 18func newBenchmarker() *benchmarker { 19 return &benchmarker{ 20 measurements: make(map[string]*types.SpecMeasurement), 21 } 22} 23 24func (b *benchmarker) Time(name string, body func(), info ...interface{}) (elapsedTime time.Duration) { 25 t := time.Now() 26 body() 27 elapsedTime = time.Since(t) 28 29 b.mu.Lock() 30 defer b.mu.Unlock() 31 measurement := b.getMeasurement(name, "Fastest Time", "Slowest Time", "Average Time", "s", 3, info...) 32 measurement.Results = append(measurement.Results, elapsedTime.Seconds()) 33 34 return 35} 36 37func (b *benchmarker) RecordValue(name string, value float64, info ...interface{}) { 38 b.mu.Lock() 39 measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", "", 3, info...) 40 defer b.mu.Unlock() 41 measurement.Results = append(measurement.Results, value) 42} 43 44func (b *benchmarker) RecordValueWithPrecision(name string, value float64, units string, precision int, info ...interface{}) { 45 b.mu.Lock() 46 measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", units, precision, info...) 47 defer b.mu.Unlock() 48 measurement.Results = append(measurement.Results, value) 49} 50 51func (b *benchmarker) getMeasurement(name string, smallestLabel string, largestLabel string, averageLabel string, units string, precision int, info ...interface{}) *types.SpecMeasurement { 52 measurement, ok := b.measurements[name] 53 if !ok { 54 var computedInfo interface{} 55 computedInfo = nil 56 if len(info) > 0 { 57 computedInfo = info[0] 58 } 59 measurement = &types.SpecMeasurement{ 60 Name: name, 61 Info: computedInfo, 62 Order: b.orderCounter, 63 SmallestLabel: smallestLabel, 64 LargestLabel: largestLabel, 65 AverageLabel: averageLabel, 66 Units: units, 67 Precision: precision, 68 Results: make([]float64, 0), 69 } 70 b.measurements[name] = measurement 71 b.orderCounter++ 72 } 73 74 return measurement 75} 76 77func (b *benchmarker) measurementsReport() map[string]*types.SpecMeasurement { 78 b.mu.Lock() 79 defer b.mu.Unlock() 80 for _, measurement := range b.measurements { 81 measurement.Smallest = math.MaxFloat64 82 measurement.Largest = -math.MaxFloat64 83 sum := float64(0) 84 sumOfSquares := float64(0) 85 86 for _, result := range measurement.Results { 87 if result > measurement.Largest { 88 measurement.Largest = result 89 } 90 if result < measurement.Smallest { 91 measurement.Smallest = result 92 } 93 sum += result 94 sumOfSquares += result * result 95 } 96 97 n := float64(len(measurement.Results)) 98 measurement.Average = sum / n 99 measurement.StdDeviation = math.Sqrt(sumOfSquares/n - (sum/n)*(sum/n)) 100 } 101 102 return b.measurements 103} 104