| package leafnodes |
| |
| import ( |
| "math" |
| "time" |
| |
| "sync" |
| |
| "github.com/onsi/ginkgo/types" |
| ) |
| |
| type benchmarker struct { |
| mu sync.Mutex |
| measurements map[string]*types.SpecMeasurement |
| orderCounter int |
| } |
| |
| func newBenchmarker() *benchmarker { |
| return &benchmarker{ |
| measurements: make(map[string]*types.SpecMeasurement, 0), |
| } |
| } |
| |
| func (b *benchmarker) Time(name string, body func(), info ...interface{}) (elapsedTime time.Duration) { |
| t := time.Now() |
| body() |
| elapsedTime = time.Since(t) |
| |
| b.mu.Lock() |
| defer b.mu.Unlock() |
| measurement := b.getMeasurement(name, "Fastest Time", "Slowest Time", "Average Time", "s", 3, info...) |
| measurement.Results = append(measurement.Results, elapsedTime.Seconds()) |
| |
| return |
| } |
| |
| func (b *benchmarker) RecordValue(name string, value float64, info ...interface{}) { |
| b.mu.Lock() |
| measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", "", 3, info...) |
| defer b.mu.Unlock() |
| measurement.Results = append(measurement.Results, value) |
| } |
| |
| func (b *benchmarker) RecordValueWithPrecision(name string, value float64, units string, precision int, info ...interface{}) { |
| b.mu.Lock() |
| measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", units, precision, info...) |
| defer b.mu.Unlock() |
| measurement.Results = append(measurement.Results, value) |
| } |
| |
| func (b *benchmarker) getMeasurement(name string, smallestLabel string, largestLabel string, averageLabel string, units string, precision int, info ...interface{}) *types.SpecMeasurement { |
| measurement, ok := b.measurements[name] |
| if !ok { |
| var computedInfo interface{} |
| computedInfo = nil |
| if len(info) > 0 { |
| computedInfo = info[0] |
| } |
| measurement = &types.SpecMeasurement{ |
| Name: name, |
| Info: computedInfo, |
| Order: b.orderCounter, |
| SmallestLabel: smallestLabel, |
| LargestLabel: largestLabel, |
| AverageLabel: averageLabel, |
| Units: units, |
| Precision: precision, |
| Results: make([]float64, 0), |
| } |
| b.measurements[name] = measurement |
| b.orderCounter++ |
| } |
| |
| return measurement |
| } |
| |
| func (b *benchmarker) measurementsReport() map[string]*types.SpecMeasurement { |
| b.mu.Lock() |
| defer b.mu.Unlock() |
| for _, measurement := range b.measurements { |
| measurement.Smallest = math.MaxFloat64 |
| measurement.Largest = -math.MaxFloat64 |
| sum := float64(0) |
| sumOfSquares := float64(0) |
| |
| for _, result := range measurement.Results { |
| if result > measurement.Largest { |
| measurement.Largest = result |
| } |
| if result < measurement.Smallest { |
| measurement.Smallest = result |
| } |
| sum += result |
| sumOfSquares += result * result |
| } |
| |
| n := float64(len(measurement.Results)) |
| measurement.Average = sum / n |
| measurement.StdDeviation = math.Sqrt(sumOfSquares/n - (sum/n)*(sum/n)) |
| } |
| |
| return b.measurements |
| } |