1
2
3
4
5 package test
6
7 import (
8 "math/bits"
9 "testing"
10 )
11
12 func BenchmarkSwitch8Predictable(b *testing.B) {
13 benchmarkSwitch8(b, true)
14 }
15 func BenchmarkSwitch8Unpredictable(b *testing.B) {
16 benchmarkSwitch8(b, false)
17 }
18 func benchmarkSwitch8(b *testing.B, predictable bool) {
19 n := 0
20 rng := newRNG()
21 for i := 0; i < b.N; i++ {
22 rng = rng.next(predictable)
23 switch rng.value() & 7 {
24 case 0:
25 n += 1
26 case 1:
27 n += 2
28 case 2:
29 n += 3
30 case 3:
31 n += 4
32 case 4:
33 n += 5
34 case 5:
35 n += 6
36 case 6:
37 n += 7
38 case 7:
39 n += 8
40 }
41 }
42 sink = n
43 }
44
45 func BenchmarkSwitch32Predictable(b *testing.B) {
46 benchmarkSwitch32(b, true)
47 }
48 func BenchmarkSwitch32Unpredictable(b *testing.B) {
49 benchmarkSwitch32(b, false)
50 }
51 func benchmarkSwitch32(b *testing.B, predictable bool) {
52 n := 0
53 rng := newRNG()
54 for i := 0; i < b.N; i++ {
55 rng = rng.next(predictable)
56 switch rng.value() & 31 {
57 case 0, 1, 2:
58 n += 1
59 case 4, 5, 6:
60 n += 2
61 case 8, 9, 10:
62 n += 3
63 case 12, 13, 14:
64 n += 4
65 case 16, 17, 18:
66 n += 5
67 case 20, 21, 22:
68 n += 6
69 case 24, 25, 26:
70 n += 7
71 case 28, 29, 30:
72 n += 8
73 default:
74 n += 9
75 }
76 }
77 sink = n
78 }
79
80 func BenchmarkSwitchStringPredictable(b *testing.B) {
81 benchmarkSwitchString(b, true)
82 }
83 func BenchmarkSwitchStringUnpredictable(b *testing.B) {
84 benchmarkSwitchString(b, false)
85 }
86 func benchmarkSwitchString(b *testing.B, predictable bool) {
87 a := []string{
88 "foo",
89 "foo1",
90 "foo22",
91 "foo333",
92 "foo4444",
93 "foo55555",
94 "foo666666",
95 "foo7777777",
96 }
97 n := 0
98 rng := newRNG()
99 for i := 0; i < b.N; i++ {
100 rng = rng.next(predictable)
101 switch a[rng.value()&7] {
102 case "foo":
103 n += 1
104 case "foo1":
105 n += 2
106 case "foo22":
107 n += 3
108 case "foo333":
109 n += 4
110 case "foo4444":
111 n += 5
112 case "foo55555":
113 n += 6
114 case "foo666666":
115 n += 7
116 case "foo7777777":
117 n += 8
118 }
119 }
120 sink = n
121 }
122
123 func BenchmarkSwitchTypePredictable(b *testing.B) {
124 benchmarkSwitchType(b, true)
125 }
126 func BenchmarkSwitchTypeUnpredictable(b *testing.B) {
127 benchmarkSwitchType(b, false)
128 }
129 func benchmarkSwitchType(b *testing.B, predictable bool) {
130 a := []any{
131 int8(1),
132 int16(2),
133 int32(3),
134 int64(4),
135 uint8(5),
136 uint16(6),
137 uint32(7),
138 uint64(8),
139 }
140 n := 0
141 rng := newRNG()
142 for i := 0; i < b.N; i++ {
143 rng = rng.next(predictable)
144 switch a[rng.value()&7].(type) {
145 case int8:
146 n += 1
147 case int16:
148 n += 2
149 case int32:
150 n += 3
151 case int64:
152 n += 4
153 case uint8:
154 n += 5
155 case uint16:
156 n += 6
157 case uint32:
158 n += 7
159 case uint64:
160 n += 8
161 }
162 }
163 sink = n
164 }
165
166 func BenchmarkSwitchInterfaceTypePredictable(b *testing.B) {
167 benchmarkSwitchInterfaceType(b, true)
168 }
169 func BenchmarkSwitchInterfaceTypeUnpredictable(b *testing.B) {
170 benchmarkSwitchInterfaceType(b, false)
171 }
172
173 type SI0 interface {
174 si0()
175 }
176 type ST0 struct {
177 }
178
179 func (ST0) si0() {
180 }
181
182 type SI1 interface {
183 si1()
184 }
185 type ST1 struct {
186 }
187
188 func (ST1) si1() {
189 }
190
191 type SI2 interface {
192 si2()
193 }
194 type ST2 struct {
195 }
196
197 func (ST2) si2() {
198 }
199
200 type SI3 interface {
201 si3()
202 }
203 type ST3 struct {
204 }
205
206 func (ST3) si3() {
207 }
208
209 type SI4 interface {
210 si4()
211 }
212 type ST4 struct {
213 }
214
215 func (ST4) si4() {
216 }
217
218 type SI5 interface {
219 si5()
220 }
221 type ST5 struct {
222 }
223
224 func (ST5) si5() {
225 }
226
227 type SI6 interface {
228 si6()
229 }
230 type ST6 struct {
231 }
232
233 func (ST6) si6() {
234 }
235
236 type SI7 interface {
237 si7()
238 }
239 type ST7 struct {
240 }
241
242 func (ST7) si7() {
243 }
244
245 func benchmarkSwitchInterfaceType(b *testing.B, predictable bool) {
246 a := []any{
247 ST0{},
248 ST1{},
249 ST2{},
250 ST3{},
251 ST4{},
252 ST5{},
253 ST6{},
254 ST7{},
255 }
256 n := 0
257 rng := newRNG()
258 for i := 0; i < b.N; i++ {
259 rng = rng.next(predictable)
260 switch a[rng.value()&7].(type) {
261 case SI0:
262 n += 1
263 case SI1:
264 n += 2
265 case SI2:
266 n += 3
267 case SI3:
268 n += 4
269 case SI4:
270 n += 5
271 case SI5:
272 n += 6
273 case SI6:
274 n += 7
275 case SI7:
276 n += 8
277 }
278 }
279 sink = n
280 }
281
282
283 type rng uint64
284
285 func newRNG() rng {
286 return 1
287 }
288 func (r rng) next(predictable bool) rng {
289 if predictable {
290 return r + 1
291 }
292 return rng(bits.RotateLeft64(uint64(r), 13) * 0x3c374d)
293 }
294 func (r rng) value() uint64 {
295 return uint64(r)
296 }
297
View as plain text