github.com/mongodb/grip@v0.0.0-20240213223901-f906268d82b9/send/benchmark/harness_results.go (about) 1 package send 2 3 import ( 4 "fmt" 5 "math" 6 "time" 7 8 "github.com/montanaflynn/stats" 9 ) 10 11 type benchResult struct { 12 name string 13 trials int 14 duration time.Duration 15 raw []result 16 dataSize int 17 operations int 18 foundErrors *bool 19 } 20 21 func (r *benchResult) evergreenPerfFormat() ([]interface{}, error) { 22 timings := r.timings() 23 24 median, err := stats.Median(timings) 25 if err != nil { 26 return nil, err 27 } 28 29 min, err := stats.Min(timings) 30 if err != nil { 31 return nil, err 32 } 33 34 max, err := stats.Max(timings) 35 if err != nil { 36 return nil, err 37 } 38 39 out := []interface{}{ 40 map[string]interface{}{ 41 "name": r.name + "-throughput", 42 "results": map[string]interface{}{ 43 "1": map[string]interface{}{ 44 "seconds": r.roundedRuntime().Seconds(), 45 "ops_per_second": r.getThroughput(median), 46 "ops_per_second_values": []float64{ 47 r.getThroughput(min), 48 r.getThroughput(max), 49 }, 50 }, 51 }, 52 }, 53 } 54 55 if r.dataSize > 0 { 56 out = append(out, interface{}(map[string]interface{}{ 57 "name": r.name + "-MB-adjusted", 58 "results": map[string]interface{}{ 59 "1": map[string]interface{}{ 60 "seconds": r.roundedRuntime().Seconds(), 61 "ops_per_second": r.adjustResults(median), 62 "ops_per_second_values": []float64{ 63 r.adjustResults(min), 64 r.adjustResults(max), 65 }, 66 }, 67 }, 68 })) 69 } 70 71 return out, nil 72 } 73 74 func (r *benchResult) timings() []float64 { 75 out := []float64{} 76 for _, r := range r.raw { 77 out = append(out, r.duration.Seconds()) 78 } 79 return out 80 } 81 82 func (r *benchResult) totalDuration() time.Duration { 83 var out time.Duration 84 for _, trial := range r.raw { 85 out += trial.duration 86 } 87 return out 88 } 89 90 func (r *benchResult) adjustResults(data float64) float64 { return bytesToMB(r.dataSize) / data } 91 func (r *benchResult) getThroughput(data float64) float64 { return float64(r.operations) / data } 92 func (r *benchResult) roundedRuntime() time.Duration { return r.duration.Round(time.Millisecond) } 93 94 func (r *benchResult) String() string { 95 return fmt.Sprintf("name=%s, trials=%d, secs=%s", r.name, r.trials, r.duration) 96 } 97 98 func (r *benchResult) hasErrors() bool { 99 if r.foundErrors == nil { 100 var val bool 101 for _, res := range r.raw { 102 if res.err != nil { 103 val = true 104 break 105 } 106 } 107 r.foundErrors = &val 108 } 109 110 return *r.foundErrors 111 } 112 113 func (r *benchResult) errReport() []string { 114 errs := []string{} 115 for _, res := range r.raw { 116 if res.err != nil { 117 errs = append(errs, res.err.Error()) 118 } 119 } 120 return errs 121 } 122 123 type result struct { 124 duration time.Duration 125 iterations int 126 err error 127 } 128 129 func bytesToMB(numBytes int) float64 { 130 return float64(numBytes) * math.Pow(2, -20) 131 }