github.com/mongodb/grip@v0.0.0-20240213223901-f906268d82b9/send/benchmark/harness_case.go (about) 1 package send 2 3 import ( 4 "context" 5 "fmt" 6 "path/filepath" 7 "runtime" 8 "strings" 9 "time" 10 ) 11 12 type caseDefinition struct { 13 name string 14 bench benchCase 15 count int 16 numOps int 17 size int 18 iterations int 19 runtime time.Duration 20 21 cumulativeRuntime time.Duration 22 elapsed time.Duration 23 startAt time.Time 24 isRunning bool 25 } 26 27 // TimerManager is a subset of the testing.B tool, used to manage 28 // setup code. 29 type TimerManager interface { 30 ResetTimer() 31 StartTimer() 32 StopTimer() 33 } 34 35 func (c *caseDefinition) ResetTimer() { 36 c.startAt = time.Now() 37 c.elapsed = 0 38 c.isRunning = true 39 } 40 41 func (c *caseDefinition) StartTimer() { 42 c.startAt = time.Now() 43 c.isRunning = true 44 } 45 46 func (c *caseDefinition) StopTimer() { 47 if !c.isRunning { 48 panic("StopTimer called on stopped timer") 49 } 50 c.elapsed += time.Since(c.startAt) 51 c.isRunning = false 52 } 53 54 func (c *caseDefinition) roundedRuntime() time.Duration { 55 return c.runtime.Round(time.Millisecond) 56 } 57 58 func (c *caseDefinition) Run(ctx context.Context) *benchResult { 59 out := &benchResult{ 60 dataSize: c.size * c.numOps * c.count, 61 name: c.name, 62 operations: c.numOps * c.count, 63 } 64 var cancel context.CancelFunc 65 ctx, cancel = context.WithTimeout(ctx, executionTimeout) 66 defer cancel() 67 68 fmt.Println("=== RUN", out.name) 69 if c.iterations == 0 { 70 c.iterations = minIterations 71 } 72 73 benchRepeat: 74 for { 75 if ctx.Err() != nil { 76 break 77 } 78 if out.trials >= c.iterations || c.cumulativeRuntime >= c.runtime || c.cumulativeRuntime >= executionTimeout { 79 break 80 } 81 82 res := result{ 83 iterations: c.count, 84 } 85 86 start := time.Now() 87 res.err = c.bench(ctx, c, c.count, c.size, c.numOps) 88 realTestLength := time.Since(start) 89 90 res.duration = c.elapsed 91 c.cumulativeRuntime += realTestLength 92 93 switch res.err { 94 case context.DeadlineExceeded: 95 break benchRepeat 96 case context.Canceled: 97 break benchRepeat 98 case nil: 99 out.trials++ 100 c.elapsed = 0 101 out.raw = append(out.raw, res) 102 default: 103 continue 104 } 105 106 } 107 108 out.duration = out.totalDuration() 109 fmt.Printf(" --- REPORT: count=%d trials=%d iters=%d required_runtime=%s cumulative_runtime=%s\n", 110 c.count, out.trials, c.iterations, c.runtime, c.cumulativeRuntime) 111 if out.hasErrors() { 112 fmt.Printf(" --- ERRORS: %s\n", strings.Join(out.errReport(), "\n ")) 113 fmt.Printf("--- FAIL: %s (%s)\n", out.name, out.roundedRuntime()) 114 } else { 115 fmt.Printf("--- PASS: %s (%s)\n", out.name, out.roundedRuntime()) 116 } 117 118 return out 119 120 } 121 122 func (c *caseDefinition) String() string { 123 return fmt.Sprintf("name=%s, count=%d, iters=%d timeout=%s, required_runtime=%d", 124 c.name, c.count, c.iterations, executionTimeout, c.runtime) 125 } 126 127 func getProjectRoot() string { return filepath.Dir(filepath.Dir(getDirectoryOfFile())) } 128 129 func getDirectoryOfFile() string { 130 _, file, _, _ := runtime.Caller(1) 131 132 return filepath.Dir(file) 133 }