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  }