blob: d6d54234c2fe1a63bafff0a8db713ae04b5cad5a [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001package 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, 0),
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}