github.com/v2fly/tools@v0.100.0/internal/event/bench_test.go (about)

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package event_test
     6  
     7  import (
     8  	"context"
     9  	"io/ioutil"
    10  	"log"
    11  	"testing"
    12  
    13  	"github.com/v2fly/tools/internal/event"
    14  	"github.com/v2fly/tools/internal/event/core"
    15  	"github.com/v2fly/tools/internal/event/export"
    16  	"github.com/v2fly/tools/internal/event/keys"
    17  	"github.com/v2fly/tools/internal/event/label"
    18  )
    19  
    20  type Hooks struct {
    21  	A func(ctx context.Context, a int) (context.Context, func())
    22  	B func(ctx context.Context, b string) (context.Context, func())
    23  }
    24  
    25  var (
    26  	aValue  = keys.NewInt("a", "")
    27  	bValue  = keys.NewString("b", "")
    28  	aCount  = keys.NewInt64("aCount", "Count of time A is called.")
    29  	aStat   = keys.NewInt("aValue", "A value.")
    30  	bCount  = keys.NewInt64("B", "Count of time B is called.")
    31  	bLength = keys.NewInt("BLen", "B length.")
    32  
    33  	Baseline = Hooks{
    34  		A: func(ctx context.Context, a int) (context.Context, func()) {
    35  			return ctx, func() {}
    36  		},
    37  		B: func(ctx context.Context, b string) (context.Context, func()) {
    38  			return ctx, func() {}
    39  		},
    40  	}
    41  
    42  	StdLog = Hooks{
    43  		A: func(ctx context.Context, a int) (context.Context, func()) {
    44  			log.Printf("A where a=%d", a)
    45  			return ctx, func() {}
    46  		},
    47  		B: func(ctx context.Context, b string) (context.Context, func()) {
    48  			log.Printf("B where b=%q", b)
    49  			return ctx, func() {}
    50  		},
    51  	}
    52  
    53  	Log = Hooks{
    54  		A: func(ctx context.Context, a int) (context.Context, func()) {
    55  			core.Log1(ctx, "A", aValue.Of(a))
    56  			return ctx, func() {}
    57  		},
    58  		B: func(ctx context.Context, b string) (context.Context, func()) {
    59  			core.Log1(ctx, "B", bValue.Of(b))
    60  			return ctx, func() {}
    61  		},
    62  	}
    63  
    64  	Trace = Hooks{
    65  		A: func(ctx context.Context, a int) (context.Context, func()) {
    66  			return core.Start1(ctx, "A", aValue.Of(a))
    67  		},
    68  		B: func(ctx context.Context, b string) (context.Context, func()) {
    69  			return core.Start1(ctx, "B", bValue.Of(b))
    70  		},
    71  	}
    72  
    73  	Stats = Hooks{
    74  		A: func(ctx context.Context, a int) (context.Context, func()) {
    75  			core.Metric1(ctx, aStat.Of(a))
    76  			core.Metric1(ctx, aCount.Of(1))
    77  			return ctx, func() {}
    78  		},
    79  		B: func(ctx context.Context, b string) (context.Context, func()) {
    80  			core.Metric1(ctx, bLength.Of(len(b)))
    81  			core.Metric1(ctx, bCount.Of(1))
    82  			return ctx, func() {}
    83  		},
    84  	}
    85  
    86  	initialList = []int{0, 1, 22, 333, 4444, 55555, 666666, 7777777}
    87  	stringList  = []string{
    88  		"A value",
    89  		"Some other value",
    90  		"A nice longer value but not too long",
    91  		"V",
    92  		"",
    93  		"ı",
    94  		"prime count of values",
    95  	}
    96  )
    97  
    98  type namedBenchmark struct {
    99  	name string
   100  	test func(*testing.B)
   101  }
   102  
   103  func Benchmark(b *testing.B) {
   104  	b.Run("Baseline", Baseline.runBenchmark)
   105  	b.Run("StdLog", StdLog.runBenchmark)
   106  	benchmarks := []namedBenchmark{
   107  		{"Log", Log.runBenchmark},
   108  		{"Trace", Trace.runBenchmark},
   109  		{"Stats", Stats.runBenchmark},
   110  	}
   111  
   112  	event.SetExporter(nil)
   113  	for _, t := range benchmarks {
   114  		b.Run(t.name+"NoExporter", t.test)
   115  	}
   116  
   117  	event.SetExporter(noopExporter)
   118  	for _, t := range benchmarks {
   119  		b.Run(t.name+"Noop", t.test)
   120  	}
   121  
   122  	event.SetExporter(export.Spans(export.LogWriter(ioutil.Discard, false)))
   123  	for _, t := range benchmarks {
   124  		b.Run(t.name, t.test)
   125  	}
   126  }
   127  
   128  func A(ctx context.Context, hooks Hooks, a int) int {
   129  	ctx, done := hooks.A(ctx, a)
   130  	defer done()
   131  	return B(ctx, hooks, a, stringList[a%len(stringList)])
   132  }
   133  
   134  func B(ctx context.Context, hooks Hooks, a int, b string) int {
   135  	_, done := hooks.B(ctx, b)
   136  	defer done()
   137  	return a + len(b)
   138  }
   139  
   140  func (hooks Hooks) runBenchmark(b *testing.B) {
   141  	ctx := context.Background()
   142  	b.ReportAllocs()
   143  	b.ResetTimer()
   144  	var acc int
   145  	for i := 0; i < b.N; i++ {
   146  		for _, value := range initialList {
   147  			acc += A(ctx, hooks, value)
   148  		}
   149  	}
   150  }
   151  
   152  func init() {
   153  	log.SetOutput(ioutil.Discard)
   154  }
   155  
   156  func noopExporter(ctx context.Context, ev core.Event, lm label.Map) context.Context {
   157  	return ctx
   158  }