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 | "golang.org/x/tools/internal/event" |
14 | "golang.org/x/tools/internal/event/core" |
15 | "golang.org/x/tools/internal/event/export" |
16 | "golang.org/x/tools/internal/event/keys" |
17 | "golang.org/x/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 | } |
159 |
Members