github.com/mailgun/holster/v4@v4.20.0/functional/b.go (about) 1 package functional 2 3 import ( 4 "context" 5 "os" 6 "time" 7 ) 8 9 // Functional benchmark context. 10 type B struct { 11 T 12 N int 13 leaf bool 14 } 15 16 // Functional test code. 17 type BenchmarkFunc func(b *B) 18 19 func newB(name string, times int, opts ...FunctionalOption) *B { 20 b := &B{ 21 T: T{ 22 name: name, 23 writer: os.Stdout, 24 errWriter: os.Stderr, 25 }, 26 N: times, 27 leaf: true, 28 } 29 30 for _, opt := range opts { 31 opt.Apply(&b.T) 32 } 33 34 return b 35 } 36 37 func (b *B) Run(name string, fn BenchmarkFunc, opts ...FunctionalOption) TestResult { 38 b.leaf = false 39 longname := joinName(b.name, name) 40 b2 := newB(longname, b.N) 41 b2.indent++ 42 b2.writer = b.writer 43 b2.errWriter = b.errWriter 44 45 b2.invoke(b.T.ctx, fn) 46 47 if !b2.result.Pass { 48 b.result.Pass = false 49 } 50 51 return b.result 52 } 53 54 func (b *B) ResetTimer() { 55 b.result.StartTime = time.Now() 56 } 57 58 func (b *B) invoke(ctx context.Context, fn BenchmarkFunc) { 59 callFn := func() { 60 fn(b) 61 } 62 b.commonInvoke(ctx, callFn, b.postHandler) 63 } 64 65 func (b *B) postHandler() { 66 // Benchmark stats. 67 if b.leaf && b.N > 0 { 68 elapsed := b.result.EndTime.Sub(b.result.StartTime) 69 nsPerOp := float64(elapsed.Nanoseconds()) / float64(b.N) 70 perOp := time.Duration(int64(nsPerOp)) 71 b.Logf("%s\t%d\t%s/op", b.name, b.N, perOp.String()) 72 } 73 }